2012-10-10 84 views
1

我有一个问题,我想用Django的ORM来解决。我有以下类别:Django排序依据ForeignKey布尔字段

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) 

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

我目前正在生成报告,而我需要的基本上是让公司看到他们的活动中的全部,并根据与会者人数排序(注册为“出席=真”)。

我有可能给你什么,我需要一个想法,一个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)之类的东西不会给我我需要的东西,因为它只返回公司活动的一部分)。

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

回答

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') 
+0

我不排除使用额外的,因为它无论如何返回一个有效的QuerySet。太棒了。非常感谢! – JoeLinux

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

+0

这不会为我工作,因为它返回的所有事件的一个子集。我需要返回所有事件,只是按照排序顺序。 – JoeLinux

+0

@JoeLinux,更新。 – defuz

+0

感谢您的努力,但这仍然只返回事件的一个子集。我需要所有这些,包括有0注册参加=真的事件。你的答案排除他们。 – JoeLinux