#7872: Some complex lookups with Q objects (or-style) don't return all matching
model objects.
-------------------------------------+--------------------------------------
Reporter: [EMAIL PROTECTED] | Owner: nobody
Status: new | Milestone:
Component: Database wrapper | Version: SVN
Keywords: | Stage: Unreviewed
Has_patch: 0 |
-------------------------------------+--------------------------------------
When using Q objects to make some complex queries, the resulting queryset
does not contain all expected objects. Here is an example case:
Models:
{{{
class ExtendedUser(User):
"""
This class inherits (MTI-style) from auth.models.User to add extra
fields, and is the parent class
for the SupportStaff and Client classes to keep things DRY.
"""
parent = models.OneToOneField(User, parent_link=True)
middle_initial = models.CharField(max_length=10, blank=True)
title = models.CharField(max_length=50, blank=True)
office_building = models.ForeignKey("Building", null=True,
blank=True)
office_number = models.CharField(max_length=15, blank=True)
phone = models.PhoneNumberField(blank=True)
twitter = models.CharField(max_length=50, blank=True)
pownce = models.CharField(max_length=50, blank=True)
aim = models.CharField(max_length=50, blank=True)
msn = models.CharField(max_length=50, blank=True)
yahoo = models.CharField(max_length=50, blank=True)
def get_full_name(self):
if self.middle_initial:
return u"%s %s %s" % (self.first_name,
self.middle_initial, self.last_name)
else:
return super(ExtendedUser, self).get_full_name()
def __unicode__(self):
return u"%s" % self.get_full_name()
class Meta:
ordering = ('last_name', 'first_name')
verbose_name = u'Extended User'
verbose_name_plural = u'Extended Users'
class SupportStaff(ExtendedUser):
"""
This class inherits from the model class ExtendedUser (itself a
subclass of auth User model).
This should only be used for people who are going to provide end-
user support services.
"""
parent = models.OneToOneField(ExtendedUser, parent_link=True)
coverage = models.ManyToManyField("OrgUnit",
related_name="support_staff_coverage", null=True, blank=True)
expertise = models.ManyToManyField("SpecialSkill",
related_name="support_staff_expertise", null=True, blank=True)
def __unicode__(self):
return u"%s" % self.get_full_name()
class SupportTicket(models.Model):
call_source = models.ForeignKey("CallSource", null=True,
blank=True)
client = models.ManyToManyField(Client)
call_description = models.TextField("Call Description",
max_length=500)
call_type = models.ManyToManyField("CallType")
equipment_tag = models.CharField(max_length=50, null=True,
blank=True)
priority = models.CharField(choices=PRIORITY_LEVELS, default=3,
max_length=2)
target_date = models.DateTimeField("Target Date and Time",
null=True, blank=True)
call_status = models.ForeignKey("CallStatus")
cause = models.ManyToManyField("Cause", null=True, blank=True)
solution = models.TextField(max_length=500, blank=True)
date_created = models.DateTimeField(default=datetime.datetime.now,
editable=False)
created_by = models.ForeignKey(SupportStaff,
related_name='ticket_created')
date_modified = models.DateTimeField(null=True, blank=True,
editable=False)
last_modified_by = models.ForeignKey(SupportStaff,
related_name='ticket_modified_by', null=True, blank=True)
date_closed = models.DateTimeField(null=True, blank=True)
closed_by = models.ForeignKey(User,
related_name='ticket_closed_by', null=True, blank=True)
class Assignment(models.Model):
support_ticket = models.ForeignKey(SupportTicket,
edit_inline=models.STACKED, num_in_admin=1,
related_name='assignment_made')
group_assigned = models.ForeignKey(Group, core=True)
group_notified = models.NullBooleanField(editable=False)
support_staff_assigned = models.ForeignKey(SupportStaff,
related_name='staff_assignment', null=True, blank=True)
support_staff_notified = models.NullBooleanField(editable=False)
notes = models.TextField(max_length=500, blank=True)
acknowledge = models.BooleanField(default=False)
date_created = models.DateTimeField(default=datetime.datetime.now,
editable=False)
created_by = models.ForeignKey(SupportStaff,
related_name='assigned_by')
date_modified =
models.DateTimeField(default=datetime.datetime.now, editable=False)
last_modified_by = models.ForeignKey(SupportStaff,
related_name='assignment_modified_by', null=True, blank=True)
date_acknowledged = models.DateTimeField(null=True, blank=True,
editable=False)
}}}
Queries:
{{{
>>> t4 =
SupportTicket.objects.filter(assignment_made__group_assigned__user=u)
>>> t5 = SupportTicket.objects.filter(created_by__parent__parent=u)
>>> t6 =
SupportTicket.objects.filter(Q(assignment_made__group_assigned__user=u)|Q(created_by__parent__parent=u)).distinct()
>>> t4
[<SupportTicket: 3>, <SupportTicket: 2>, <SupportTicket: 1>]
>>> t5
[<SupportTicket: 5>, <SupportTicket: 3>, <SupportTicket: 2>,
<SupportTicket: 1>]
>>> t6
[<SupportTicket: 3>, <SupportTicket: 2>, <SupportTicket: 1>]
>>>
str(SupportTicket.objects.filter(Q(assignment_made__group_assigned__user=u)|Q(created_by__parent__parent=u)).distinct().query)
'SELECT DISTINCT "tickets_supportticket"."id",
"tickets_supportticket"."call_source_id",
"tickets_supportticket"."call_description",
"tickets_supportticket"."equipment_tag",
"tickets_supportticket"."priority", "tickets_supportticket"."target_date",
"tickets_supportticket"."call_status_id",
"tickets_supportticket"."solution",
"tickets_supportticket"."date_created",
"tickets_supportticket"."created_by_id",
"tickets_supportticket"."date_modified",
"tickets_supportticket"."last_modified_by_id",
"tickets_supportticket"."date_closed",
"tickets_supportticket"."closed_by_id" FROM "tickets_supportticket" LEFT
OUTER JOIN "tickets_assignment" ON ("tickets_supportticket"."id" =
"tickets_assignment"."support_ticket_id") INNER JOIN "auth_group" ON
("tickets_assignment"."group_assigned_id" = "auth_group"."id") LEFT OUTER
JOIN "auth_user_groups" ON ("auth_group"."id" =
"auth_user_groups"."group_id") WHERE ("auth_user_groups"."user_id" = 6 OR
"tickets_supportticket"."created_by_id" = 6 ) ORDER BY
"tickets_supportticket"."date_created" DESC'
}}}
--
Ticket URL: <http://code.djangoproject.com/ticket/7872>
Django Code <http://code.djangoproject.com/>
The web framework for perfectionists with deadlines
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at
http://groups.google.com/group/django-updates?hl=en
-~----------~----~----~----~------~----~------~--~---