我有一个数据库,其中包含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过滤器的原因之一 - 后者允许您简洁地说出您的意思。据推测,前者也可以允许查询表达,但我越来越绝望地认为这种解决方案很简单。
旁注:你不需要'过滤器的额外调用()',你可以做'SKU.objects.exclude(...)' – voithos
谢谢,好知道。 – shanusmagnus
是否要求所有与清单1无关的skus,或与清单1以外的清单相关的所有skus?或者“没有为清单1定义”意味着其他什么? – dokkaebi