>
> I have a class like this:
>
> class Node:
> name = models.CharField()
> parents = models.ManyToManyField('self', symmetrical=False,
> related_name='child_nodes', null=True, blank=True)
>
> This allows a basic parent(s)/children hierarchy. A node can have >=
> 0 parents. A parent can have >= 0 children.
>
> Say I have these nodes:
>
> A - parent node
> B - parent node
> C - child of both A & B
>
> So I can do this:
>
> Node.objects.filter(name='C')
> > returns ['C' node].
>
> Node.objects.filter(name='C', parents__name='A')
> > returns ['C' node].
>
> Node.objects.filter(name='C', parents__name='B')
> > returns ['C' node].
>
> Node.objects.filter(Q(name='C'), Q(parents__name='A'))
> > returns ['C' node].
>
> Node.objects.filter(Q(name='C'), Q(parents__name='B'))
> > returns ['C' node].
>
> Node.objects.filter(Q(name='C'), Q(parents__name='A'),
> Q(parents__name='B'))
> > returns []
>
> Node.objects.filter(Q(name='C') & Q(parents__name='A') &
> Q(parents__name='B'))
> > returns []
>
> Node.objects.filter(Q(parents__name='A'), Q(parents__name='B'))
> > returns []
>
>
> Why do those last two return an empty set? I can even do this:
>
> Node.objects.filter(Q(name='C'),
> Q(parents__name='A')).filter(Q(parents__name='B'))
> > returns ['C' node].
>
> That works. But filtering on two parents (AND, not OR... I want the
> child nodes of both parents) returns the empty set. It doesn't make
> sense to me why using two separate filters would work, but combining
> them into one statement gives different results.
>
> Anyone have an idea about this? Is this a bug in the django query
> system, or am I looking at this wrong? Thanks.
>
You're looking at it wrong. When you put multiple filter specs into
one filter call for a m2m join, what you are actually doing is adding
extra conditions to the m2m join.
So this one:
Node.objects.filter(Q(parents__name='A'), Q(parents__name='B'))
This is looking for a single node who has a single parent whose name
is both 'A' and 'B' - unlikely!
And this one:
Node.objects.filter(Q(parents__name='A')).filter(Q(parents__name='B'))
This is looking for a node which has a parent with name A, and a
parent with name B.
This is all clearly documented, see here:
http://docs.djangoproject.com/en/1.2/topics/db/queries/#spanning-multi-valued-relationships
Cheers
Tom
--
You received this message because you are subscribed to the Google Groups "Django users" group.
To post to this group, send email to django-users@googlegroups.com.
To unsubscribe from this group, send email to django-users+unsubscribe@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/django-users?hl=en.
No comments:
Post a Comment