Django按外键排序布尔字段

时间:2012-10-10 10:52:06

标签: python sql django django-queryset

我有一个问题,我想用Django的ORM来解决。我有以下课程:

class Company:
    name = models.CharField(max_length=200)

class Event:
    title = models.CharField(max_length=200)
    company = models.ForeignKey(Company)

class Registration:
    attended = models.BooleanField(default=False)
    event = models.ForeignKey(Event)

这些是简单的例子,但基本上公司可以有几个事件。当用户注册参加活动时,会为该用户创建注册(我知道该字段不存在,这不是问题)。如果用户实际显示事件,则该用户的Registration对象将具有“attend = True”。

我目前正在生成报告,而我所需要的实际上是让公司看到所有活动的方式,并按与会者人数排序(注册人数为“参加人数=真实”) )。

我有一个SQL语句,可以让你知道我需要什么(除了“e.title”,显然一个QuerySet会让我回到整个对象):

SELECT e.title FROM example_event e LEFT JOIN (SELECT event_id,
COUNT(*) attendees FROM example_registration WHERE attended=1 GROUP BY
event_id) r ON (e.id=r.event_id) ORDER BY r.attendees DESC;

这给了我一个正确排序的事件标题结果集。但我真的想在ORM中执行此操作并返回QuerySet。有没有办法做到这一点?我基本上需要这样的东西:

events.annotate(attendees=Count('registration__attended=True'))
                .order_by('attendees')

......我知道这句话是无效的,但它希望能够解决我想要完成的事情。此外,我需要始终为公司返回所有事件,因为它是一份报告。他们希望看到他们所有活动的表现如何,即使他们有0个与会者(因此像events.filter(registration__attended=True)这样的东西不会给我我需要的东西,因为它只返回公司活动的一部分)。 / p>

在此先感谢,我真的很感谢有人的帮助!

2 个答案:

答案 0 :(得分:3)

我不确定您是否要排除使用extra方法,但您可以执行以下操作:

events = Event.objects.extra(
    select={'attendees': 'SELECT COUNT(*) from event_registration' + \
        ' where attended=1 and event_id=event_event.id'}
).order_by('attendees')

答案 1 :(得分:0)

这应该有效:

events.filter(registration__attended=True)\
      .annotate(attendees=Count('registration'))\
      .order_by('attendees')

注意filter()annotate()方法不可交换。所以查询之间存在差异:

>>> events.annotate(attendees=Count('registration')).filter(registration__attended=True)

>>> events.filter(registration__attended=True).annotate(attendees=Count('registration'))

documentation中阅读更多内容。