Skip to content

Commit 146aff3

Browse files
committed
Fixed django#18590 - Reverted Python 2.4 workaround for Model pickling
Revert of 08d521e. Refs django#10547, django#12121. Thanks Michal Petrucha for the report.
1 parent 1aa0d8a commit 146aff3

File tree

1 file changed

+11
-29
lines changed

1 file changed

+11
-29
lines changed

django/db/models/base.py

Lines changed: 11 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
from django.db import (router, transaction, DatabaseError,
1717
DEFAULT_DB_ALIAS)
1818
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
2020
from django.db.models.deletion import Collector
2121
from django.db.models.options import Options
2222
from django.db.models import signals
@@ -400,25 +400,16 @@ def __reduce__(self):
400400
need to do things manually, as they're dynamically created classes and
401401
only module-level classes can be pickled by the default path.
402402
"""
403+
if not self._deferred:
404+
return super(Model, self).__reduce__()
403405
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.
410406
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)
422413

423414
def _get_pk_val(self, meta=None):
424415
if not meta:
@@ -926,20 +917,11 @@ def get_absolute_url(opts, func, self, *args, **kwargs):
926917
class Empty(object):
927918
pass
928919

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):
939921
"""
940922
Used to unpickle Model subclasses with deferred fields.
941923
"""
942-
cls = factory(model, attrs)
924+
cls = deferred_class_factory(model, attrs)
943925
return cls.__new__(cls)
944926
model_unpickle.__safe_for_unpickle__ = True
945927

0 commit comments

Comments
 (0)