I have a model which has a ForeignKey to itself, intended to mark
duplicates similar to a bug/ticket-tracking system:

class Bug(models.Model):
    name = models.CharField(maxlength=64)
    duplicate_of = models.ForeignKey('self', related_name='duplicates', 
null=True)
    def __str__(self):
        return self.name

When searching through bug names for a particular string, I don't want
the duplicate bugs to appear; instead, I want both bugs with a matching
name and bugs whose set of duplicates contains one with a matching name.
I would have expected this filter to work:

Bug.objects.filter(
    Q(name__contains=string) | Q(duplicates__name__contains=string),
    duplicate_of__isnull=True)

It doesn't.  Instead, I get this very surprising behavior:

    >>> for t in Bug.objects.all():
    ...     print t.name, t.duplicate_of
    ...
    eggs1 None
    eggs2 spam
    spam None
    >>> qs = Bug.objects.filter(duplicate_of__isnull=True)
    >>> r1 = qs.filter(name__contains='eggs')
    >>> r2 = qs.filter(duplicates__name__contains='eggs')
    >>> r1
    [<Bug: eggs1>]
    >>> r2
    [<Bug: spam>]
    >>> r1 | r2
    [<Bug: spam>]
    >>>

It seems that this is because Django is using INNER JOIN in its query:

SELECT
    "test_bug"."id","test_bug"."name","test_bug"."duplicate_of_id"
FROM
    "test_bug"
INNER JOIN
    "test_bug" AS "test_bug__duplicates"
ON
    "test_bug"."id" = "test_bug__duplicates"."duplicate_of_id"
WHERE
    (("test_bug"."duplicate_of_id" IS NULL AND
      "test_bug"."name" LIKE %eggs% ESCAPE '\')
    OR
     ("test_bug"."duplicate_of_id" IS NULL AND
      "test_bug__duplicates"."name" LIKE %eggs% ESCAPE '\'))

Replacing the INNER JOIN with a LEFT OUTER JOIN gives me the results I
expected.

Is this a bug, or am I doing something silly?

-Zak

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Django users" 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-users?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to