2012-10-10 87 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