[Django] #28456: Defining __getstate__ in class derived from Model doesn't affect model pickling

9 views
Skip to first unread message

Django

unread,
Jul 31, 2017, 3:09:56 PM7/31/17
to django-...@googlegroups.com
#28456: Defining __getstate__ in class derived from Model doesn't affect model
pickling
-------------------------------------+-------------------------------------
Reporter: Nerl~ | Owner: nobody
Type: New | Status: new
feature |
Component: Database | Version: 1.11
layer (models, ORM) |
Severity: Normal | Keywords: Pickle, Models
Triage Stage: | Has patch: 1
Unreviewed |
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
-------------------------------------+-------------------------------------
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.
[https://docs.python.org/3/library/pickle.html#object.__getstate__ 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.

--
Ticket URL: <https://code.djangoproject.com/ticket/28456>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

Django

unread,
Jul 31, 2017, 4:10:56 PM7/31/17
to django-...@googlegroups.com
#28456: Defining __getstate__ in class derived from Model doesn't affect model
pickling
-------------------------------------+-------------------------------------
Reporter: Nerl~ | Owner: Nerl~
Type: | Status: assigned
Cleanup/optimization |
Component: Database layer | Version: 1.11
(models, ORM) |
Severity: Normal | Resolution:

Keywords: Pickle, Models | Triage Stage:
| Unreviewed
Has patch: 1 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Nerl~):

* owner: nobody => Nerl~
* status: new => assigned
* type: New feature => Cleanup/optimization


--
Ticket URL: <https://code.djangoproject.com/ticket/28456#comment:1>

Django

unread,
Jul 31, 2017, 9:03:09 PM7/31/17
to django-...@googlegroups.com
#28456: Defining __getstate__ in class derived from Model doesn't affect model
pickling
-------------------------------------+-------------------------------------
Reporter: Nerl~ | Owner: Nerl~
Type: | Status: assigned
Cleanup/optimization |
Component: Database layer | Version: 1.11
(models, ORM) |
Severity: Normal | Resolution:
Keywords: Pickle, Models | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Tim Graham):

* stage: Unreviewed => Accepted


Comment:

[https://github.com/django/django/pull/8833 PR]

--
Ticket URL: <https://code.djangoproject.com/ticket/28456#comment:2>

Django

unread,
Aug 7, 2017, 12:21:09 AM8/7/17
to django-...@googlegroups.com
#28456: Defining __getstate__ in class derived from Model doesn't affect model
pickling
-------------------------------------+-------------------------------------
Reporter: Nerl~ | Owner: Nerl~
Type: | Status: assigned
Cleanup/optimization |
Component: Database layer | Version: 1.11
(models, ORM) |
Severity: Normal | Resolution:
Keywords: Pickle, Models | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by Chris Adams):

Ran the tests and all worked for me.

--
Ticket URL: <https://code.djangoproject.com/ticket/28456#comment:3>

Django

unread,
Aug 8, 2017, 8:17:41 AM8/8/17
to django-...@googlegroups.com
#28456: Defining __getstate__ in class derived from Model doesn't affect model
pickling
-------------------------------------+-------------------------------------
Reporter: Nerl~ | Owner: Nerl~
Type: | Status: assigned
Cleanup/optimization |
Component: Database layer | Version: 1.11
(models, ORM) |
Severity: Normal | Resolution:
Keywords: Pickle, Models | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 1

Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Tim Graham):

* needs_better_patch: 0 => 1


--
Ticket URL: <https://code.djangoproject.com/ticket/28456#comment:4>

Django

unread,
Aug 11, 2017, 3:27:39 PM8/11/17
to django-...@googlegroups.com
#28456: Defining __getstate__ in class derived from Model doesn't affect model
pickling
-------------------------------------+-------------------------------------
Reporter: Nerl~ | Owner: Nerl~
Type: | Status: closed

Cleanup/optimization |
Component: Database layer | Version: 1.11
(models, ORM) |
Severity: Normal | Resolution: fixed
Keywords: Pickle, Models | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 1

Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Tim Graham <timograham@…>):

* status: assigned => closed
* resolution: => fixed


Comment:

In [changeset:"97cb3bd16d8e50d96eb184f8d67dd1723f776d2a" 97cb3bd1]:
{{{
#!CommitTicketReference repository=""
revision="97cb3bd16d8e50d96eb184f8d67dd1723f776d2a"
Fixed #28456 -- Allowed customizing Model pickling by overriding
__getstate__().
}}}

--
Ticket URL: <https://code.djangoproject.com/ticket/28456#comment:5>

Reply all
Reply to author
Forward
0 new messages