开发者

Django queryset to match all related objects

Let's say I have a ForeignKey from Coconut to Swallow (ie, a swallow has carried many coconuts, but each coconut has been carried by only one swallow). Now let's say that I have a ForeignKey from husk_segment 开发者_Go百科to Coconut.

Now, I have a list of husk_segments and I want to find out if ALL of these have been carried gripped by a particular swallow.

I can have swallow.objects.filter(coconuts_carried__husk_sements__in = husk_segment_list) to show that this swallow has gripped at least one husk segment in the list. Now, how can I show that every husk segment that the swallow has ever carried are in this list?


I can have swallow.objects.filter(coconuts_carried__husk_sements__in = husk_segment_list) to show that this swallow has gripped at least one husk segment in the list.

No, this is wrong, this gives you a list of swallows which have carried at least one husk segment from *husk_segment_list*.

If I've understood right, we are talking about checking for a specific swallow.

So, from your description I guess your models look something like this:

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')

If you already have the husk segment list you need to check againts the swallows segments, there's no reason you need to resolve it in a query. Get the swallows' segments and check if it's a superset of your husk segment list.

So we have:

#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)


See the docs on queries spanning multi-valued relationships -- you should chain filter calls.

A simple way to go would be something like

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

A fancy way to do this in one line using reduce would be

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


If i understood your altered question correctly you should be able to compare the coconut_carried_set of the swallow with the list of coconuts that have been carried.

see docs

I'm not entirely sure that this is what you want - I guess it depends on if you know which swallow you want to check beforehand or if you want to check it against all swallows - in that case there may be a better solution.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜