Django:通过相关的模型字段从查询集中删除重复项(分组依据)

时间:2018-05-30 16:16:52

标签: python django

我有一个带有几条记录的Queryset,我不想使用相关的模型字段删除重复项。例如:

class User(models.Model):
    group = models.ForeignKey('Group')
    ...

class Address(models.Model):
    ...
    models.ForeignKey('User')

addresses = Address.objects.filter(user__group__id=1).order_by('-id')

这将返回一个地址记录的QuerySet,我想按用户ID分组。

  • 我无法使用.annotate,因为我需要来自地址的所有字段,以及地址和用户之间的关系
  • 我无法使用.distinct()因为它不起作用,因为所有地址都是不同的,我想要不同的用户地址。

我可以:

addresses = Address.objects.filter(user__group__id=1).order_by('-id')
unique_users_ids = []
unique_addresses = []

for address in addresses:
    if address.user.id not in unique_users_ids:
        unique_addresses.append(address)
        unique_users_ids.append(address.user.id)

print unique_addresses # TA-DA!

但对于一个简单的事情来说似乎太过分了(该死的Django)。

有没有简单的方法来实现这一目标?

1 个答案:

答案 0 :(得分:4)

使用.distinct()使用字段名称

Django还有一个.distinct(..)函数,它将列名称作为输入列,应该是唯一的。唉大多数数据库系统都不支持这个(据我所知只有PostgreSQL)。但是在PostgreSQL中我们可以执行:

# Limited number of database systems support this
addresses = (Address.objects
                    .filter(user__group__id=1)
                    .order_by('-id')
                    .distinct('user_id'))

使用两个查询

处理此问题的另一种方法是首先使用一个适用于用户的查询,并为每个用户获取最大的address_id

from django.db.models import Max

address_ids = (User.objects
                   .annotate(address_id=Max('address_set__id'))
                   .filter(address_id__isnull=False)
                   .values_list('address_id'))

现在,对于每个用户,我们计算出最大的对应address_id,并且我们消除了没有地址的User。然后,我们获取id s。

的列表

在第二步中,我们获取地址:

addresses = Address.objects.filter(pk__in=address_ids)