diff --git a/django/db/models/base.py b/django/db/models/base.py
index 82283d5..79af1cb 100644
|
a
|
b
|
from django.db.models.fields.related import (ManyToOneRel,
|
| 16 | 16 | from django.db import (router, transaction, DatabaseError, |
| 17 | 17 | DEFAULT_DB_ALIAS) |
| 18 | 18 | from django.db.models.query import Q |
| 19 | | from django.db.models.query_utils import DeferredAttribute |
| | 19 | from django.db.models.query_utils import DeferredAttribute, deferred_class_factory |
| 20 | 20 | from django.db.models.deletion import Collector |
| 21 | 21 | from django.db.models.options import Options |
| 22 | 22 | from django.db.models import signals |
| … |
… |
class Model(object):
|
| 400 | 400 | need to do things manually, as they're dynamically created classes and |
| 401 | 401 | only module-level classes can be pickled by the default path. |
| 402 | 402 | """ |
| | 403 | if not self._deferred: |
| | 404 | return super(Model, self).__reduce__() |
| 403 | 405 | data = self.__dict__ |
| 404 | | model = self.__class__ |
| 405 | | # The obvious thing to do here is to invoke super().__reduce__() |
| 406 | | # for the non-deferred case. Don't do that. |
| 407 | | # On Python 2.4, there is something weird with __reduce__, |
| 408 | | # and as a result, the super call will cause an infinite recursion. |
| 409 | | # See #10547 and #12121. |
| 410 | 406 | defers = [] |
| 411 | | if self._deferred: |
| 412 | | from django.db.models.query_utils import deferred_class_factory |
| 413 | | factory = deferred_class_factory |
| 414 | | for field in self._meta.fields: |
| 415 | | if isinstance(self.__class__.__dict__.get(field.attname), |
| 416 | | DeferredAttribute): |
| 417 | | defers.append(field.attname) |
| 418 | | model = self._meta.proxy_for_model |
| 419 | | else: |
| 420 | | factory = simple_class_factory |
| 421 | | return (model_unpickle, (model, defers, factory), data) |
| | 407 | for field in self._meta.fields: |
| | 408 | if isinstance(self.__class__.__dict__.get(field.attname), |
| | 409 | DeferredAttribute): |
| | 410 | defers.append(field.attname) |
| | 411 | model = self._meta.proxy_for_model |
| | 412 | return (model_unpickle, (model, defers), data) |
| 422 | 413 | |
| 423 | 414 | def _get_pk_val(self, meta=None): |
| 424 | 415 | if not meta: |
| … |
… |
def get_absolute_url(opts, func, self, *args, **kwargs):
|
| 926 | 917 | class Empty(object): |
| 927 | 918 | pass |
| 928 | 919 | |
| 929 | | def simple_class_factory(model, attrs): |
| 930 | | """Used to unpickle Models without deferred fields. |
| 931 | | |
| 932 | | We need to do this the hard way, rather than just using |
| 933 | | the default __reduce__ implementation, because of a |
| 934 | | __deepcopy__ problem in Python 2.4 |
| 935 | | """ |
| 936 | | return model |
| 937 | | |
| 938 | | def model_unpickle(model, attrs, factory): |
| | 920 | def model_unpickle(model, attrs): |
| 939 | 921 | """ |
| 940 | 922 | Used to unpickle Model subclasses with deferred fields. |
| 941 | 923 | """ |
| 942 | | cls = factory(model, attrs) |
| | 924 | cls = deferred_class_factory(model, attrs) |
| 943 | 925 | return cls.__new__(cls) |
| 944 | 926 | model_unpickle.__safe_for_unpickle__ = True |
| 945 | 927 | |