Hi Malcolm,

After the queryset-refactor merge, code like this breaks:

  Foo.objects.none() | Foo.object.filter(bar=123)

(This kind of thing is useful sometimes when building up a QuerySet in 
stages.  That isn't one of the use cases given for .none() in the 
docs, but the test suite does say "none() returns an EmptyQuerySet 
that behaves like any other QuerySet object", so it would be nice if 
the above worked).

I've created a patch, which special cases EmptyQuerySet in a couple of 
places, which seems to be the simplest way of doing it.  I can commit 
it myself, but I wanted to pass it by you first since I'm unfamiliar 
with qs-rf, and in case you disagree about fixing this -- patch 
attached.

Luke

-- 
"Where a person wishes to attract, they should always be ignorant." 
(Jane Austen)

Luke Plant || http://lukeplant.me.uk/

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en
-~----------~----~----~----~------~----~------~--~---

Index: django/db/models/query.py
===================================================================
--- django/db/models/query.py	(revision 7509)
+++ django/db/models/query.py	(working copy)
@@ -132,15 +132,25 @@
 
     def __and__(self, other):
         self._merge_sanity_check(other)
-        combined = self._clone()
-        combined.query.combine(other.query, sql.AND)
-        return combined
+        if self.__class__ is EmptyQuerySet:
+            return self
+        elif other.__class__ is EmptyQuerySet:
+            return other
+        else:            
+            combined = self._clone()
+            combined.query.combine(other.query, sql.AND)
+            return combined
 
     def __or__(self, other):
         self._merge_sanity_check(other)
-        combined = self._clone()
-        combined.query.combine(other.query, sql.OR)
-        return combined
+        if self.__class__ is EmptyQuerySet:
+            return other
+        elif other.__class__ is EmptyQuerySet:
+            return self
+        else:
+            combined = self._clone()
+            combined.query.combine(other.query, sql.OR)
+            return combined
 
     ####################################
     # METHODS THAT DO DATABASE QUERIES #
@@ -495,6 +505,9 @@
         """
         Checks that we are merging two comparable queryset classes.
         """
+        if self.__class__ is EmptyQuerySet or other.__class__ is EmptyQuerySet:
+            return
+
         if self.__class__ is not other.__class__:
             raise TypeError("Cannot merge querysets of different types ('%s' and '%s'."
                     % (self.__class__.__name__, other.__class__.__name__))
Index: tests/modeltests/lookup/models.py
===================================================================
--- tests/modeltests/lookup/models.py	(revision 7509)
+++ tests/modeltests/lookup/models.py	(working copy)
@@ -270,6 +270,14 @@
 0
 >>> [article for article in Article.objects.none().iterator()]
 []
+>>> Article.objects.none() | Article.objects.filter(headline='Article 1')
+[<Article: Article 1>]
+>>> Article.objects.none() & Article.objects.filter(headline='Article 1')
+[]
+>>> Article.objects.filter(headline='Article 1') | Article.objects.none()
+[<Article: Article 1>]
+>>> Article.objects.filter(headline='Article 1') & Article.objects.none()
+[]
 
 # using __in with an empty list should return an empty query set
 >>> Article.objects.filter(id__in=[])

Reply via email to