|
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 |
@@ -400,25 +400,16 @@ def __reduce__(self): |
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: |
@@ -926,20 +917,11 @@ 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 |
|
|
0 commit comments