2011-07-21 63 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

相關問題