Code

Ticket #12121: 12121.reduce_deferred.diff

File 12121.reduce_deferred.diff, 3.4 KB (added by emulbreh, 4 years ago)
Line 
1Index: django/db/models/base.py
2===================================================================
3--- django/db/models/base.py    (revision 11690)
4+++ django/db/models/base.py    (working copy)
5@@ -344,31 +344,6 @@
6     def __hash__(self):
7         return hash(self._get_pk_val())
8 
9-    def __reduce__(self):
10-        """
11-        Provide pickling support. Normally, this just dispatches to Python's
12-        standard handling. However, for models with deferred field loading, we
13-        need to do things manually, as they're dynamically created classes and
14-        only module-level classes can be pickled by the default path.
15-        """
16-        data = self.__dict__
17-        if not self._deferred:
18-            return super(Model, self).__reduce__()
19-        defers = []
20-        pk_val = None
21-        for field in self._meta.fields:
22-            if isinstance(self.__class__.__dict__.get(field.attname),
23-                    DeferredAttribute):
24-                defers.append(field.attname)
25-                if pk_val is None:
26-                    # The pk_val and model values are the same for all
27-                    # DeferredAttribute classes, so we only need to do this
28-                    # once.
29-                    obj = self.__class__.__dict__[field.attname]
30-                    model = obj.model_ref()
31-
32-        return (model_unpickle, (model, defers), data)
33-
34     def _get_pk_val(self, meta=None):
35         if not meta:
36             meta = self._meta
37@@ -647,15 +622,6 @@
38 class Empty(object):
39     pass
40 
41-def model_unpickle(model, attrs):
42-    """
43-    Used to unpickle Model subclasses with deferred fields.
44-    """
45-    from django.db.models.query_utils import deferred_class_factory
46-    cls = deferred_class_factory(model, attrs)
47-    return cls.__new__(cls)
48-model_unpickle.__safe_for_unpickle__ = True
49-
50 if sys.version_info < (2, 5):
51     # Prior to Python 2.5, Exception was an old-style class
52     def subclass_exception(name, parent, unused):
53Index: django/db/models/query_utils.py
54===================================================================
55--- django/db/models/query_utils.py     (revision 11690)
56+++ django/db/models/query_utils.py     (working copy)
57@@ -237,8 +237,29 @@
58     overrides["Meta"] = Meta
59     overrides["__module__"] = model.__module__
60     overrides["_deferred"] = True
61+    overrides['__reduce__'] = deferred_model_reduce
62     return type(name, (model,), overrides)
63+deferred_class_factory.__safe_for_unpickling__ = True
64 
65-# The above function is also used to unpickle model instances with deferred
66-# fields.
67-deferred_class_factory.__safe_for_unpickling__ = True
68+def deferred_model_reduce(self):
69+    data = self.__dict__
70+    defers = []
71+    pk_val = None
72+    for field in self._meta.fields:
73+        if isinstance(self.__class__.__dict__.get(field.attname),
74+                DeferredAttribute):
75+            defers.append(field.attname)
76+            if pk_val is None:
77+                # The pk_val and model values are the same for all
78+                # DeferredAttribute classes, so we only need to do this
79+                # once.
80+                obj = self.__class__.__dict__[field.attname]
81+                model = obj.model_ref()
82+
83+    return (deferred_model_unpickle, (model, defers), data)
84+
85+def deferred_model_unpickle(model, attrs):
86+    cls = deferred_class_factory(model, attrs)
87+    return cls.__new__(cls)
88+deferred_model_unpickle.__safe_for_unpickle__ = True
89+