Django queryset匹配所有相关对象

时间:2011-07-21 22:48:17

标签: django django-queryset

假设我有一个从椰子到燕子的外来钥匙(也就是说,一只燕子已携带许多椰子,但每只椰子只携带一只燕子)。现在让我们说我有一个从husk_segment到Coconut的ForeignKey。

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

我可以使用swallow.objects.filter(coconuts_carried__husk_sements__in = husk_segment_list)来显示此燕子已经抓住了列表中的至少一个外壳片段。现在,我怎样才能证明燕子所携带的每个稻壳都在这个清单中?

3 个答案:

答案 0 :(得分: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())

答案 1 :(得分: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细分列表,则需要再次检查吞咽细分,您无需在查询中解决它。获取燕子的片段并检查它是否是您的果壳片段列表的超集。

所以我们有:

#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 :(得分:0)

如果我正确地理解了你改变的问题,你应该能够将燕子的椰子莴苣与已经携带的椰子列表进行比较。

请参阅docs

我不完全确定这是你想要的 - 我想这取决于你是否知道你想要事先检查哪个燕子,或者你想要检查所有燕子 - 在这种情况下可能会有更好的溶液