【问题标题】:Django ORM: count a subset of related itemsDjango ORM:计算相关项目的子集
【发布时间】:2011-04-23 14:56:45
【问题描述】:

我正在寻找一种方法来使用相关项目子集的计数来注释查询集。以下是我的模型的一个子集:

class Person(models.Model):
    Name = models.CharField(max_length = 255)
    PracticeAttended = models.ManyToManyField('Practice',
                                              through = 'PracticeRecord')

class Club(models.Model):
    Name = models.CharField(max_length = 255)
    Slug = models.SlugField()
    Members = models.ManyToManyField('Person')

class PracticeRecord(PersonRecord):
    Person = models.ForeignKey(Person)
    Practice = models.ForeignKey(Practice)

class Practice(models.Model):
    Club = models.ForeignKey(Club, default = None, null = True)
    Date = models.DateField()

我正在寻找一个查询集来注释一个人参加的俱乐部特定实践的数量。我已经可以通过查询Person.objects.all().annotate(Count('PracticeRecord'))找到那个人的练习总数

但是我想以某种方式注释一个人参加特定俱乐部的练习次数。

我更喜欢使用 django ORM 的东西,而不必求助于编写原始 SQL。

谢谢。

【问题讨论】:

    标签: django django-models django-orm


    【解决方案1】:

    但是我想以某种方式注释一个人参加特定俱乐部的练习次数。

    让我们看看。

    首先,找到具体的俱乐部。

    club = Club.objects.get(**conditions)
    

    接下来,过滤所有在这个俱乐部练习过的人。

    persons = Person.objects.filter(practicerecord__Practice__Club = club)
    

    现在,用计数进行注释。

    q = persons.annotate(count = Count('practicerecord'))
    

    编辑

    我能够在我的测试设置中成功完成这项工作:Django 1.2.3、Python 2.6.4、Postgresql 8.4、Ubuntu Karmic。

    PS:为字段使用小写名称是一个好主意™。这使得使用双下划线 (__) 语法链接字段变得更加容易。例如在您的情况下,Django 会自动为每个 Person 创建 practicerecord。当您尝试通过此字段访问PracticeRecord 的其他字段时,您必须记住使用标题大小写。

    如果您使用小写名称,您可以这样写:

    persons = Person.objects.filter(practicerecord__practice__club = club)
    #                                               ^^        ^^  
    

    看起来更加统一。

    PPS:是Count('practicerecord')(注意小写)。

    【讨论】:

    • 哇,这很酷,而且效果很好......我不知道如果我过滤特定字段,那么聚合也会在过滤后的行上。出于好奇,您知道是否在任何地方的文档中都提到了这种行为?
    【解决方案2】:

    恐怕原始 sql 是这里唯一的选择。反正把它交给模型管理器也没那么可怕和难管理。

    【讨论】:

    • 奇怪。我能够在不使用 Raw SQL 的情况下让它工作。在 Django 1.2.3、Postgresql 8.4、Python 2.6.4、Ubuntu Karmic 中测试。
    • 是的,过滤原始查询集后有注释的方法。我认为任务是在不过滤人员的情况下注释练习记录。
    猜你喜欢
    • 2015-10-10
    • 1970-01-01
    • 1970-01-01
    • 2018-11-25
    • 2018-06-03
    • 1970-01-01
    • 1970-01-01
    • 2011-04-18
    • 1970-01-01
    相关资源
    最近更新 更多