2012-09-29 41 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