在 Django 中聚合分组字段时返回对象

Posted

技术标签:

【中文标题】在 Django 中聚合分组字段时返回对象【英文标题】:Return object when aggregating grouped fields in Django 【发布时间】:2018-11-20 02:41:33 【问题描述】:

假设以下示例模型:

# models.py
class event(models.Model):
    location = models.CharField(max_length=10)
    type = models.CharField(max_length=10)
    date = models.DateTimeField()
    attendance = models.IntegerField()

我想使用 Django ORM 获取每个活动地点和类型组合的最新日期的出席人数。根据Django Aggregation documentation,我们可以通过在annotation 前面使用values 来实现类似的效果。

...原始结果根据 values() 子句中指定的字段的唯一组合进行分组。然后为每个唯一组提供注释;注释是在组的所有成员上计算的。

所以使用示例模型,我们可以这样写:

event.objects.values('location', 'type').annotate(latest_date=Max('date'))

确实按位置和类型对事件进行分组,但不返回 attendance 字段,这是所需的行为。

我尝试的另一种方法是使用 distinct 即:

event.objects.distinct('location', 'type').annotate(latest_date=Max('date'))

但我得到一个错误

NotImplementedError: annotate() + distinct(fields) is not implemented.

我找到了一些依赖于 Django 数据库特定功能的答案,但我想找到一个与底层关系数据库无关的解决方案。

【问题讨论】:

好吧,你永远不能 100% 不可知:django 在 ORM 中提供的所有功能在某种程度上都与 relational 数据库提供的通用功能相关,但还有其他类型的graphical 和级联(例如 MongoDB)等数据库。 你是对的,我应该澄清我的意思是关系。我会更新我的问题。 注解value字段是什么意思? 抱歉,应该是attendance。我会再更新一次! 所以,如果我理解您要正确执行的操作,您是在尝试弄清楚有多少人将参加一个活动,比如音乐会? 【参考方案1】:

好的,我认为这个可能真的适合你。它基于一个假设,我认为这是正确的。

当您创建模型对象时,它们都应该是唯一的。您似乎不太可能在同一个 date 上拥有两个 events,在同一个 type 的同一个 location 上。所以有了这个假设,让我们开始吧:(作为格式说明,Names 类倾向于以大写字母开头,以区分classesvariablesinstances。)

# First you get your desired events with your criteria.
results = Event.objects.values('location', 'type').annotate(latest_date=Max('date'))

# Make an empty 'list' to store the values you want.
results_list = []

# Then iterate through your 'results' looking up objects
# you want and populating the list.
for r in results:
    result = Event.objects.get(location=r['location'], type=r['type'], date=r['latest_date'])
    results_list.append(result)

# Now you have a list of objects that you can do whatever you want with.

您可能需要查找 Max(Date) 的确切输出,但这应该可以让您走上正确的道路。

【讨论】:

我认为这行不通。注释返回一个不包含attendance 键的字典。 您是否尝试将出勤率添加到值中? 您不能这样做,因为这会在注释之前创建独特的位置/类型/出勤组合。我只需要独特的位置/类型组合。 感谢您提供更新的答案。不幸的是,我已经尝试过了,但它不起作用。 annotate 之后的第二个 values “破坏”了第一个 values 提供的唯一组合的分组。结果,您将获得每个事件对象的出席情况。 好的。这是我的最后一枪。更新了答案。

以上是关于在 Django 中聚合分组字段时返回对象的主要内容,如果未能解决你的问题,请参考以下文章

mysql之聚合函数

聚合石墨烯/django 查询中的字段

072:Django数据库ORM聚合函数详解-aggregate和annotate

聚合函数和分组查询(有宝藏)

聚合函数和分组查询(有宝藏)

Django聚合函数与分组查询