Django 查询集。如何只预取唯一的?

Posted

技术标签:

【中文标题】Django 查询集。如何只预取唯一的?【英文标题】:Django querysets. How to prefetch only unique? 【发布时间】:2021-09-16 09:49:47 【问题描述】:

型号:

class House(Model)

class Flat(Model):
    house = ForeignKey(House, related_name="houses")
    owner = ForeignKey(User)

class User(Model)

查询集:

queryset = User.objects.prefetch_related(
    Prefetch("flats", queryset=Flat.objects.select_related("houses"))

然后是公寓:

% for flat in user.flats.all %
<p>№  flat.number ,  flat.house.name </p>
% endfor %

没关系。但是对于房子我只需要独特的

% for flat in user.flats.all %
<p>House  flat.house.name </p>
% endfor %

但是这个模板给了我所有的房子,有重复的。 我怎样才能避免重复,有什么想法吗?我尝试了 .distinct() 但它不起作用,看起来我使用 distinct() 错误等。

【问题讨论】:

【参考方案1】:

仅找到带有模板过滤器的解决方案。 查询集:

queryset = User.objects.filter(status="ACTIVE").prefetch_related(
        Prefetch("flats", queryset=Flat.objects.select_related("house"))
    )

有了这个,我可以为每个用户获得所有公寓:

% for user in object_list %
    % for flat in user.flats.all %
         flat.number ,  flat.house.name 
    % endfor %
% endfor %

我正在使用模板过滤器来获得独特的房子。

% for user in object_list %
    % for flat in user.flats.all|get_unique_houses %
         flat.house.name 
    % endfor %
% endfor %

# extra_tags.py
@register.filter(name="get_unique_houses")
def get_unique_houses(value):
    return value.distinct('house')

【讨论】:

【参考方案2】:

如果用户是多个flats 中的owner,您可能最终会得到重复的房屋,这些flats 都在同一个house 中。要通过Flats 获取用户相关的所有房屋,您可以使用不同的查询,以House 开头,以便您可以使用distinct

distinct_houses = House.objects.filter(flats__owner=user).distinct()

上面为用户是所有者的每个公寓返回一个 House 对象,并确保您没有重复项。 (请注意,以上假设 house = ForeignKey(House, related_name="flats")related_name 已更改为 flats,因为相关名称中的“房屋”似乎是与 Flat 模型相关的拼写错误。)

或者,如果您仍然需要通过原始queryset = User.objects.prefetch_related(...) 了解所有Flats 并且不想要额外的查询,您也可以在Python 中做一些内存中的操作。喜欢:

distinct_houses = flat.house for flat in user.flats.all()

旁注:基于外键字段名称为 house,您似乎需要使用 Flat.objects.select_related('house') 而不是 Flat.objects.select_related('houses') 有错字。

【讨论】:

但问题是我需要为每个用户提供所有公寓和独特房屋的用户查询。

以上是关于Django 查询集。如何只预取唯一的?的主要内容,如果未能解决你的问题,请参考以下文章

Django 1.9.5:偶尔出现反向查找字段的 FieldError

获取基于字段的唯一对象的查询集 - Django

Django预取相关并存在

Django Rest:AssertionError:无法将唯一查询与非唯一查询组合

如何使用 UICollectionView 选择要预取的项目数?

如何使用 Django 中另一个查询集的结果过滤查询集?