【问题标题】:Django querysets. How to prefetch only unique?Django 查询集。如何只预取唯一的?
【发布时间】: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() 错误等。

【问题讨论】:

    标签: django django-models orm django-templates django-orm


    【解决方案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') 有错字。

      【讨论】:

      • 但问题是我需要为每个用户提供所有公寓和独特房屋的用户查询。
      猜你喜欢
      • 2018-05-30
      • 2020-01-10
      • 2012-06-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-18
      • 2018-09-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多