2011-07-21 65 views
4

假设我有一个从Coconut到Swallow的ForeignKey(即,一只燕子携带了很多椰子,但是每个椰子只被一只燕子携带)。现在让我们说我有一个从husk_segment到Coconut的ForeignKey。Django查询集匹配所有相关的对象

现在,我有一个husk_segments的列表,我想知道是否所有这些都被特定的燕子抓住了。

我可以通过swallow.objects.filter(coconuts_carried__husk_sements__in = husk_segment_list)来表明这只燕子已经抓住了列表中的至少一个稻壳片段。现在,我怎么能证明燕子曾经携带过的每一片稻壳都在这个列表中?

+0

如果添加了模型的基本结构,它可能会更容易理解事物的结构。 – niklasdstrom

回答

2

我可以有swallow.objects.filter(coconuts_carried__husk_sements__in = husk_segment_list),以表示这个燕子把持在列表中的至少一个 壳段。

不,这是不对的,这给你燕子的列表,它已经从* husk_segment_list携带的至少一个壳段*。

如果我理解正确,我们正在讨论检查特定的燕子。

所以,从你的描述我猜你的模型看起来是这样的:

class Swallow(models.Model): 
    name = models.CharField(max_length=100) 


class Coconut(models.Model): 
    swallow = models.ForeignKey(Swallow, related_name='coconuts_carried') 



class HuskSegment(models.Model): 
    coconut = models.ForeignKey(Coconut, related_name='husk_segments') 

如果你已经拥有你需要检查反对票燕子段果壳段列表中,没有任何理由,你需要解决它在查询中。获取燕子片段并检查它是否是你的壳片段列表的超集。

因此,我们有:

#husk_segment_list = [<object: HuskSegment>, <object: HuskSegment>, <object: HuskSegment>...] 
husk_segments_set = set((husk.pk for husk in husk_segment_list)) 

whitey = Swallow.object.get(name='Neochelidon tibialis') 
wh_segments_set = set((value[0] for value in HuskSegment.objects.filter(coconut__in=whitey.coconuts_carried.all()).values_list('id'))) 

whitey_has_carried_all = wh_segments_set.issuperset(husk_segments_set) 
2

请参阅the docs on queries spanning multi-valued relationships - 您应该链接过滤器调用。

一个简单的方法去将像

queryset = Swallow.objects.all() 
for coconut in coconuts: 
    queryset = queryset.filter(coconuts_carried=coconut) 

一个奇特的方式使用reduce做到这一条线是

reduce(lambda q, c: q.filter(coconuts_carried=c), coconuts, Swallow.objects.all()) 
+0

我想过(循环,而不是减少/实验室),但它不是特别优雅,是吗?如何使用AND循环Q对象?你认为这个解决方案好还是坏? – jMyles

+0

我刚才意识到我误解了这个问题:我实际上需要确保燕子携带的所有椰子都在列表中,而不是列表中的每个椰子都被燕子携带。 – jMyles

0

如果我理解你的改变问题正确,您应该能够比较燕子的coconut_carried_set和已经携带的椰子列表。

看到docs

我不能完全肯定这是你想要的 - 我想这取决于如果你知道哪些吞下要事先检查,或者如果你要检查它反对一切燕子 - 中这种情况下可能会有更好的解决方案。

+0

哦,麻烦 - 我再次修改了这个问题。 :-) – jMyles

相关问题