Commit a97f690e authored by Malcolm Tredinnick's avatar Malcolm Tredinnick
Browse files

Added the ability to pickle and unpickle QuerySets and Query classes.


git-svn-id: http://code.djangoproject.com/svn/django/trunk@7499 bcc190cf-cafb-0310-a4f2-bffc1f526a37
parent db80f57c
Loading
Loading
Loading
Loading
+12 −1
Original line number Diff line number Diff line
@@ -28,6 +28,17 @@ class QuerySet(object):
    # PYTHON MAGIC METHODS #
    ########################

    def __getstate__(self):
        """
        Allows the Queryset to be pickled.
        """
        # Force the cache to be fully populated.
        len(self)

        obj_dict = self.__dict__.copy()
        obj_dict['_iter'] = None
        return obj_dict

    def __repr__(self):
        return repr(list(self))

@@ -37,7 +48,7 @@ class QuerySet(object):
        # whilst not messing up any existing iterators against the queryset.
        if self._result_cache is None:
            if self._iter:
                self._result_cache = list(self._iter())
                self._result_cache = list(self._iter)
            else:
                self._result_cache = list(self.iterator())
        elif self._iter:
+18 −0
Original line number Diff line number Diff line
@@ -99,6 +99,24 @@ class Query(object):
        memo[id(self)] = result
        return result

    def __getstate__(self):
        """
        Pickling support.
        """
        obj_dict = self.__dict__.copy()
        del obj_dict['connection']
        return obj_dict

    def __setstate__(self, obj_dict):
        """
        Unpickling support.
        """
        self.__dict__.update(obj_dict)
        # XXX: Need a better solution for this when multi-db stuff is
        # supported. It's the only class-reference to the module-level
        # connection variable.
        self.connection = connection

    def get_meta(self):
        """
        Returns the Options instance (the model._meta) from which to start
+23 −0
Original line number Diff line number Diff line
@@ -376,6 +376,29 @@ You can evaluate a ``QuerySet`` in the following ways:
      iterating over a ``QuerySet`` will take advantage of your database to
      load data and instantiate objects only as you need them.


Pickling QuerySets
~~~~~~~~~~~~~~~~~~

If you pickle_ a ``QuerySet``, this will also force all the results to be
loaded into memory prior to pickling. This is because pickling is usually used
as a precursor to caching and when the cached queryset is reloaded, you want
the results to already be present. This means that when you unpickle a
``QuerySet``, it contains the results at the moment it was pickled, rather
than the results that are currently in the database.

If you only want to pickle the necessary information to recreate the
``Queryset`` from the database at a later time, pickle the ``query`` attribute
of the ``QuerySet``. You can then recreate the original ``QuerySet`` (without
any results loaded) using some code like this::

    >>> import pickle
    >>> query = pickle.loads(s)     # Assuming 's' is the pickled string.
    >>> qs = MyModel.objects.all()
    >>> qs.query = query            # Restore the original 'query'.

.. _pickle: http://docs.python.org/lib/module-pickle.html

Limiting QuerySets
------------------