Ticket #12121: 12121.reduce_deferred.diff

File 12121.reduce_deferred.diff, 3.4 KB (added by emulbreh, 5 years ago)
  • django/db/models/base.py

     
    344344    def __hash__(self):
    345345        return hash(self._get_pk_val())
    346346
    347     def __reduce__(self):
    348         """
    349         Provide pickling support. Normally, this just dispatches to Python's
    350         standard handling. However, for models with deferred field loading, we
    351         need to do things manually, as they're dynamically created classes and
    352         only module-level classes can be pickled by the default path.
    353         """
    354         data = self.__dict__
    355         if not self._deferred:
    356             return super(Model, self).__reduce__()
    357         defers = []
    358         pk_val = None
    359         for field in self._meta.fields:
    360             if isinstance(self.__class__.__dict__.get(field.attname),
    361                     DeferredAttribute):
    362                 defers.append(field.attname)
    363                 if pk_val is None:
    364                     # The pk_val and model values are the same for all
    365                     # DeferredAttribute classes, so we only need to do this
    366                     # once.
    367                     obj = self.__class__.__dict__[field.attname]
    368                     model = obj.model_ref()
    369 
    370         return (model_unpickle, (model, defers), data)
    371 
    372347    def _get_pk_val(self, meta=None):
    373348        if not meta:
    374349            meta = self._meta
     
    647622class Empty(object):
    648623    pass
    649624
    650 def model_unpickle(model, attrs):
    651     """
    652     Used to unpickle Model subclasses with deferred fields.
    653     """
    654     from django.db.models.query_utils import deferred_class_factory
    655     cls = deferred_class_factory(model, attrs)
    656     return cls.__new__(cls)
    657 model_unpickle.__safe_for_unpickle__ = True
    658 
    659625if sys.version_info < (2, 5):
    660626    # Prior to Python 2.5, Exception was an old-style class
    661627    def subclass_exception(name, parent, unused):
  • django/db/models/query_utils.py

     
    237237    overrides["Meta"] = Meta
    238238    overrides["__module__"] = model.__module__
    239239    overrides["_deferred"] = True
     240    overrides['__reduce__'] = deferred_model_reduce
    240241    return type(name, (model,), overrides)
     242deferred_class_factory.__safe_for_unpickling__ = True
    241243
    242 # The above function is also used to unpickle model instances with deferred
    243 # fields.
    244 deferred_class_factory.__safe_for_unpickling__ = True
     244def deferred_model_reduce(self):
     245    data = self.__dict__
     246    defers = []
     247    pk_val = None
     248    for field in self._meta.fields:
     249        if isinstance(self.__class__.__dict__.get(field.attname),
     250                DeferredAttribute):
     251            defers.append(field.attname)
     252            if pk_val is None:
     253                # The pk_val and model values are the same for all
     254                # DeferredAttribute classes, so we only need to do this
     255                # once.
     256                obj = self.__class__.__dict__[field.attname]
     257                model = obj.model_ref()
     258
     259    return (deferred_model_unpickle, (model, defers), data)
     260
     261def deferred_model_unpickle(model, attrs):
     262    cls = deferred_class_factory(model, attrs)
     263    return cls.__new__(cls)
     264deferred_model_unpickle.__safe_for_unpickle__ = True
     265
Back to Top