2012-09-29 78 views
4

我有一個數據庫,其中包含skus,套件,kit_contents和清單的模式。這裏是「一切爲包記錄定義kitcontent記錄中定義的單品在清單1中定義的給我」爲查詢:如何讓Django QuerySet'exclude'正常工作?

SELECT DISTINCT s.* FROM skus s 
JOIN kit_contents kc ON kc.sku_id = s.id 
JOIN kits k   ON k.id = kc.kit_id 
JOIN checklists c ON k.checklist_id = 1; 

我使用Django的,我主要是很喜歡的ORM,因爲我可以表達通過查詢:

skus = SKU.objects.filter(kitcontent__kit__checklist_id=1).distinct() 

這是這種瀏覽所有外鍵一個漂亮的方式。 Django的ORM產生與上面寫的SQL基本相同。問題在於,我不清楚如何獲得爲清單1定義的所有SKU 而不是。在上面的SQL查詢中,我將通過用「!=」替換「=」來做到這一點。但是Django的模型沒有一個不等於運算符。你應該使用排除()方法,其中一個可能已經猜到是這樣的:

skus = SKU.objects.filter().exclude(kitcontent__kit__checklist_id=1).distinct() 

但Django的產生此查詢,這是不一樣的東西:

SELECT distinct s.* FROM skus s 
WHERE NOT ((skus.id IN 
    (SELECT kc.sku_id FROM kit_contents kc 
    INNER JOIN kits k ON (kc.kit_id = k.id) 
    WHERE (k.checklist_id = 1 AND kc.sku_id IS NOT NULL)) 
AND skus.id IS NOT NULL)) 

(爲了便於閱讀和比較,我已經清理了查詢。)

我是Django ORM的初學者,我希望儘可能使用它。有沒有辦法在這裏得到我想要的東西?

編輯:

karthikr給了一個答案,不出於同樣的原因工作原ORM .exclude()解決方案不起作用:一個SKU可以在kit_contents在存在套件checklist_id = 1和checklist_id = 2。使用通過手查詢我張開後與使用「checklist_id = 1」產生34分的結果,使用「checklist_id = 2」產生53分的結果,和下面的查詢產生26分的結果:

SELECT DISTINCT s.* FROM skus s 
JOIN kit_contents kc ON kc.sku_id = s.id 
JOIN kits k   ON k.id = kc.kit_id 
JOIN checklists c ON k.checklist_id = 1 
JOIN kit_contents kc2 ON kc2.sku_id = s.id 
JOIN kits k2   ON k2.id = kc2.kit_id 
JOIN checklists c2 ON k2.checklist_id = 2; 

我認爲這是人們似乎找不到.exclude()解決方案合理取代某種not_equals過濾器的原因之一 - 後者允許您簡潔地說出您的意思。據推測,前者也可以允許查詢表達,但我越來越絕望地認​​爲這種解決方案很簡單。

+0

旁註:你不需要'過濾器的額外調用()',你可以做'SKU.objects.exclude(...)' – voithos

+0

謝謝,好知道。 – shanusmagnus

+0

是否要求所有與清單1無關的skus,或與清單1以外的清單相關的所有skus?或者「沒有爲清單1定義」意味着其他什麼? – dokkaebi

回答

1

您可以這樣做 - 獲取清單1的所有對象,並將其從完整列表中排除。

sku_ids = skus.values_list('pk', flat=True) 
non_checklist_1 = SKU.objects.exclude(pk__in=sku_ids).distinct() 
+0

感謝您的回答;但看到我的編輯,爲什麼它不工作。 – shanusmagnus