Opened 16 years ago
Closed 12 years ago
#7700 closed Bug (fixed)
Query parent for child
Reported by: | Owned by: | nobody | |
---|---|---|---|
Component: | Core (Other) | Version: | dev |
Severity: | Normal | Keywords: | |
Cc: | Vlastimil Zíma | Triage Stage: | Accepted |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
I'm not sure if this is a feature request or a bug fix :) This seemed to work a few weeks ago, and it no longer does. Whether or not the feature was intentional, it was quite useful--being able to query parent models for child instances. Given the following model:
from django.contrib.auth.models import Group class Team(Group): pass
I want to query the Groups to find out which are Teams. This used to work
>>> g = Group.objects.create(name='group1') >>> t = Team.objects.create(name='team1') >>> Group.objects.filter(team__pk__isnull=False) [<Group: team1>]
But instead now I get the following:
>>> Group.objects.filter(team__pk__isnull=False) [<Group: group1>, <Group: team1>]
Ideally, it would be nice to simplify this to:
>>> Group.objects.filter(team__isnull=False) [<Group: team1>]
But just getting it to work again would be nice.
Change History (11)
follow-up: 2 comment:1 by , 16 years ago
Triage Stage: | Unreviewed → Design decision needed |
---|
comment:2 by , 16 years ago
Replying to jamesturk:
unclear as to why this is advantageous over using Team.objects.all() / using child class directly when only children are wanted, ticket probably needs elaboration
A more compelling example might be a case where a model only has a foreign key to a parent model. For example:
from django.contrib.auth.models import Group class Team(Group): pass
>>> g = Group.objects.create(name='group1') >>> t = Team.objects.create(name='team1') >>> u = User.objects.create(username='val') >>> u.groups = (g,t) >>> u.groups.filter(team__isnull=False) [<Group: team1>]
Of course, this can be done:
>>> u.groups.filter(pk__in=(list(Team.objects.all()))) [<Group: team1>]
But besides code complexity, it also results in an extra database query.
comment:3 by , 16 years ago
Component: | Uncategorized → Core framework |
---|
comment:4 by , 14 years ago
Triage Stage: | Design decision needed → Accepted |
---|
If this behaviour is still occurring, it's a flat out bug. The query discussed here is normal reverse-relation querying, as model inheritance is Python syntactic sugar for a one-to-one relation. You should definitely be able to do it and the query returning <Group: group1>
in the report is returning an incorrect result. Needs verifying that the reported problem still exists, but, if it does, we should fix it.
follow-up: 6 comment:5 by , 14 years ago
It still seems to be exhibiting the same behavior. Using 1.2.1, I get the following.
Model definition:
from django.contrib.auth.models import Group class Team(Group): pass
Model creation:
>>> g = Group.objects.create(name='group1') >>> t = Team.objects.create(name='team1')
Expected behavior:
>>> Team.objects.all() [<Team: team1>] >>> Group.objects.all() [<Group: group1>, <Group: team1>]
Unexpected behavior:
>>> Group.objects.filter(team__pk__isnull=False) [<Group: group1>, <Group: team1>] >>> Group.objects.filter(team__isnull=False) [<Group: group1>, <Group: team1>]
comment:6 by , 14 years ago
Cc: | added |
---|
Replying to cdeccio:
It still seems to be exhibiting the same behavior. Using 1.2.1, I get the following.
I found out that following works fine and even looks good:
>>> Group.objects.filter(team=None) [<Group: group1>] >>> Group.objects.exclude(team=None) [<Group: team1>]
And SQLs looks like:
SELECT U0."id" FROM "auth_group" U0 LEFT OUTER JOIN "myapp_team" U1 ON (U0."id" = U1."group_ptr_id") WHERE U1."group_ptr_id" IS NULL SELECT U0."id" FROM "auth_group" U0 WHERE NOT ( U0."id" IN ( SELECT U0."id" FROM "auth_group" U0 LEFT OUTER JOIN "myapp_team" U1 ON (U0."id" = U1."group_ptr_id") WHERE U1."group_ptr_id" IS NULL ) )
comment:7 by , 14 years ago
Severity: | → Normal |
---|---|
Type: | → Bug |
comment:10 by , 12 years ago
The above queries work as they should. I just tested them with django's master branch.
In [1]: Group.objects.filter(team__pk__isnull=True) Out[1]: [<Group: group1>] In [2]: Group.objects.filter(team__pk__isnull=False) Out[2]: [<Group: team1>]
comment:11 by , 12 years ago
Resolution: | → fixed |
---|---|
Status: | new → closed |
unclear as to why this is advantageous over using Team.objects.all() / using child class directly when only children are wanted, ticket probably needs elaboration