我有一个问题,我想用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>
在此先感谢,我真的很感谢有人的帮助!
答案 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中阅读更多内容。