Wednesday, October 6, 2010

Django and the none()

The Django manager has a none() method that can retury an empty queryset:
def none(self):
        return self.get_empty_query_set()

def get_empty_query_set(self):
        return EmptyQuerySet(self.model)
class EmptyQuerySet(QuerySet):
    def __init__(self, model=None, query=None):
        super(EmptyQuerySet, self).__init__(model, query)
        self._result_cache = []

    def __and__(self, other):
        return self._clone()

    def __or__(self, other):
        return other._clone()

    def count(self):
        return 0

    def delete(self):

    def _clone(self, klass=None, setup=False, **kwargs):
        c = super(EmptyQuerySet, self)._clone(klass, **kwargs)
        c._result_cache = []
        return c
I tried it out too:
>>> from import Event

>>> Event.objects

>>> Event.objects.none()
>>> []

>>> Event.objects.filter(id=100000000) (for a non-existent Event)
>>> []
The QuerySet class also has a __nonzero__() operator that is used when there is an if statement used, which makes the logic perform exactly the same if the queryset were actually a list.

Called to implement truth value testing, and the built-in operation bool(); should return False or True, or their integer equivalents 0 or 1. When this method is not defined, __len__ is called, if it is defined. If a class defines neither __len__ nor __nonzero__, all its instances are considered true.
def __nonzero__(self):
        if self._result_cache is not None:
            return bool(self._result_cache)
        except StopIteration:
            return False
        return True

No comments:

Post a Comment