【问题标题】:Django query objects grouped on field按字段分组的 Django 查询对象
【发布时间】:2015-06-02 00:58:31
【问题描述】:

如果我有这样的 django 模型:

class Person(models.Model):
    given_names = models.CharField(max_length=144)
    surname = models.CharField(max_length=144)

我想构建一个查询,该查询将返回数据库中的所有人,按他们的姓氏分组。它应该返回如下内容:

{
    'Smith': [<Person: Joseph A Smith>, <Person: Joseph B Smith>],
    'Bloggs': [<Person: Joseph A Bloggs>, <Person: Joseph B Bloggs>],
    ...
}

构建此查询的最佳方法是什么?

【问题讨论】:

  • [&lt;Person: Joseph A Smith&gt;, &lt;Person: Joseph B Smith&gt;] 是列表还是查询集?
  • 对于我目前的情况,没关系。为了论证,我们假设查询集。

标签: python django database django-models


【解决方案1】:
from collections import defaultdict

result = defaultdict(list)
persons = Person.objects.all()
for person in persons:
    result[person.surname].append(person)

问题是像“SMith”、“SMITH”或“Smith”这样的姓氏。在这种情况下,将 result[person.surname]... 替换为 result[person.surname.strip().lower()]... 会有所帮助。

【讨论】:

    【解决方案2】:

    完全按照您的要求进行操作的一种方法是为每个姓氏创建一个查询集,遍历姓氏,然后将它们添加到字典中,如下所示:

    for name in Person.objects.values('surname').distinct():
        qs = Person.objects.filter(surname__icontains=name)
        your_dict[name] = qs
    

    并将其添加到字典中。

    您也可以考虑使用Person 的外键将姓氏设为自己的模型。您可以遍历所有姓氏,例如:

    for s in Surname.objects.all():
        people = Person.objects.filter(surname=s.name)
        your_dict[s.name] = people
    

    最后,您可以使用原始 SQL,如果您使用的是 MySQL,则可以尝试以下操作(对于 Postgres,您需要一些不同的东西):

    people = Person.objects.raw(
        'SELECT surname, GROUP_CONCAT(given_names) FROM personapp_person GROUP BY surname'
    )
    

    但我认为其他解决方案最终会更容易。

    【讨论】:

    • 嗯。我希望得到一个可以在一个查询中完成所有操作的答案。顺便说一句,您可以直接使用 Person.objects.values('surname').distinct() 获取所有不同的姓氏 - 不需要第一个循环。
    • @Tom 谢谢,很好的反馈!我认为这不可能直接使用 ORM,但您可以根据您的数据库类型尝试原始 SQL...更新了我的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-01-18
    • 2012-01-30
    • 2014-08-27
    • 1970-01-01
    • 2016-01-10
    • 2010-09-27
    • 2011-05-08
    相关资源
    最近更新 更多