Opened 8 years ago
Closed 8 years ago
#28456 closed Cleanup/optimization (fixed)
Defining __getstate__ in class derived from Model doesn't affect model pickling
| Reported by: | Nerl~ | Owned by: | Nerl~ |
|---|---|---|---|
| Component: | Database layer (models, ORM) | Version: | 1.11 |
| Severity: | Normal | Keywords: | Pickle, Models |
| Cc: | Triage Stage: | Accepted | |
| Has patch: | yes | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | yes |
| Easy pickings: | no | UI/UX: | no |
Description
Current implementation of Model.__reduce__ does not allow to simply override what attributes should or shouldn't be serialized in classes derived from Model class. Pickle documentation says that for that purpose developer can define __getstate__ method in class and return dictionary with needed content. That case isn't represented in Model.__reduce__ by now, current implementation just using __dict___ attribute without copying it so it's difficult to change what attributes must be pickled in derived classes.
For example, some model derived from Model class and adds attribute to model instance that cannot be pickled or just shouldn't be:
class MyModel(Model):
def __init__(self, *args, **kwargs):
self.service_obj = UnpickleableService() # some service that shouldn't be pickled, just for example
super().__init__(*args, **kwargs)
Now it's hard to define that attribute service_obj mustn't be pickled - what you need to do is define __reduce__ method in derived class and copy third attribute from result of the super method and then delete service_obj key from that, otherwise you will delete service_obj from original __dict__ attribute:
class MyModel(Model):
def __init__(self, *args, **kwargs):
self.service_obj = UnpickleableService()
super().__init__(*args, **kwargs)
def __reduce__(self):
callable, args, data = super().__reduce__()
data = data.copy()
del data['service_obj']
return data
Pickle documentation propose easier way for doing so with defining __getstate__ method that returns object with content that must be pickled. If that method is absent then __dict__ attribute will be used. With this implementation, Django can define simple __getstate__ method in Model class that will return copy of __dict__ attribute. Developer can define __getstate__ method in derived classes and specify what should or shouldn't be serialized by pickle in that particular model.
That approach helps to write mixins for models or model hierarchy that will add some attributes to model instance and exclude them from pickling results. Also it corresponds to the Pickle documentation.
Change History (5)
comment:1 by , 8 years ago
| Owner: | changed from to |
|---|---|
| Status: | new → assigned |
| Type: | New feature → Cleanup/optimization |
comment:2 by , 8 years ago
| Triage Stage: | Unreviewed → Accepted |
|---|
comment:4 by , 8 years ago
| Patch needs improvement: | set |
|---|
PR