2013-03-25 36 views
8

我正在使用Django的內置用戶模型,並有一個自定義的Foo對象與外鍵給用戶。我在尋找,選擇所有用戶對象和所有符合一定的約束富的對象,像這樣:Django左外連接過濾器

SELECT * from auth_user LEFT OUTER JOIN "foo" ON 
(auth_user.id = foo.id AND <other criteria here>) 

我應該如何在Django做到這一點?到目前爲止,我已經試過:

User.objects.filter(foo__<criteria>) 

但產生類似這樣的SQL:

SELECT * from auth_user LEFT OUTER JOIN "foo" ON 
(auth_user.id = foo.id) WHERE <other criteria here> 

,並只返回有符合標準的Foo對象的用戶對象。或者,我可以選擇所有用戶對象併爲每個用戶運行一個查詢,但效率會大大降低。

+0

其他標準是什麼?這一切仍然與'Foo'模型有關嗎? – Ngenator 2013-03-25 19:31:01

+0

是的。 Foo包含一對夫婦日期字段,我只從指定的日期範圍中選擇Foos。 – Phobophobia 2013-03-25 22:02:16

+0

'User.objects.filter(foo__ )'應該做什麼? '用戶'模型中'foo'不是字段。我從來沒有能夠生成具有'LEFT OUTER JOIN'的查詢。 – user2233706 2013-08-16 04:05:21

回答

1

如果你想的Django獲取所有的User對象和所有相關的用戶對象的Foo對象,那麼你會使用select_related()

User.objects.all().select_related('foo') 

但在這裏,你不想所有Foo與用戶對象相關的對象,您只需要它們的子集滿足您的條件。我不知道如何告訴Django在單個查詢集中執行此操作。但是你可以是做什麼都分別選擇並做在Python中加入:

# Map from user id to corresponding Foo satisfying <criteria>, if any. 
foos = {foo.user_id: foo for foo in 
     Foo.objects.filter(user__isnull = False, <criteria>)} 
for user in User.objects.all(): 
    foo = foos.get(user.id) 
    # ... 

(這並不做任何更多的數據庫的工作還是比你LEFT OUTER JOIN將傳輸更多的數據,所以我想這是一個合理的方法)

+0

完美,謝謝:) – Phobophobia 2013-03-25 22:01:19

+1

請記住,我實際上並不知道您的模型是如何相關的,所以您可能需要稍微調整我提出的解決方案以滿足您的需求。 – 2013-03-25 22:24:03

+0

您的解決方案運行以下查詢:SELECT•••FROM「auth_user」WHERE「auth_user」。「id」= 對於每個符合條件的Foo的用戶。據我所知,這與「{foo.user_id:foo」;用別的東西替換任何一個部分會導致查詢不能運行。兩個模型之間的唯一關係是Foo具有指向用戶的ForeignKey。 – Phobophobia 2013-03-25 22:30:17

1

這是笨重,但是這應該這樣做:

User.objects.raw('SELECT auth_user.* from auth_user LEFT OUTER JOIN ' 
       '"foo" ON (auth_user.id = foo.id AND ' 
       '<other criteria here>)') 

您可以將它們添加到選擇左側圖示上返回的用戶對象額外的屬性。

0

爲了得到一個LEFT OUTER JOIN你可以去:

User.objects.select_related('foo').filter(Q(foo__isnull=True) | Q(<other criteria here>)) 

Django使用foo__isnull=True引導它來生成LEFT OUTER JOIN。給foo__isnull=False生成一個INNER JOIN,因爲它沒有過濾器參數。