[Django] #28188: Field._get_default prevents model fields from being pickled

2 views
Skip to first unread message

Django

unread,
May 9, 2017, 8:02:25 AM5/9/17
to django-...@googlegroups.com
#28188: Field._get_default prevents model fields from being pickled
-----------------------------------------+------------------------
Reporter: Adam Alton | Owner: nobody
Type: Uncategorized | Status: new
Component: Uncategorized | Version: 1.11
Severity: Normal | Keywords:
Triage Stage: Unreviewed | Has patch: 0
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
-----------------------------------------+------------------------
The changes introduced in
[[https://github.com/django/django/commit/d2a26c1a90e837777dabdf3d67ceec4d2a70fb86
#diff-
bf776a3b8e5dbfac2432015825ef8afe|d2a26c1a90e837777dabdf3d67ceec4d2a70fb86]]
mean that in cases where a model field has a default and the default is
not a callable, the field instance cannot be pickled.

The offending line is:

{{{#!python
return lambda: self.default
}}}

This problem only exists in Django version >= 1.11.

The reason for that ''lambda'' is because the code has been refactored so
that all the logic for getting the default value has been moved into the
''_get_default'' method, which allows it to be cached with the
''@cached_property'' decorator. And then the ''get_default'' method
expects the value returned from ''_get_default'' to always be a callable.
That requirement for the value to always be a callable is the reason for
wrapping the value with ''lambda'' in the case where it's not already a
callable.

My proposed solution is to simply move the ''if callable()'' check back
out into the ''get_default'' method. This would mean that we lose a very
minor bit of efficiency because we have to run that one ''if'' statement
each time that ''get_default'' is called, but the rest of the logic would
remain inside the cached ''_get_default'' method.

I have made a commit here which contains my proposed fix and a test to
prevent regression:
https://github.com/adamalton/django/commit/a7c3f672d2ea45df2fdea8cad6ffcfa10172b133

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

Django

unread,
May 9, 2017, 8:31:01 AM5/9/17
to django-...@googlegroups.com
#28188: Field._get_default() prevents model fields from being pickled
-------------------------------------+-------------------------------------

Reporter: Adam Alton | Owner: nobody
Type: Bug | Status: new
Component: Database layer | Version: 1.11
(models, ORM) |
Severity: Release blocker | Resolution:
Keywords: | Triage Stage: Accepted

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

* type: Uncategorized => Bug
* component: Uncategorized => Database layer (models, ORM)
* severity: Normal => Release blocker
* stage: Unreviewed => Accepted


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

Django

unread,
May 9, 2017, 8:47:49 AM5/9/17
to django-...@googlegroups.com
#28188: Field._get_default() prevents model fields from being pickled
-------------------------------------+-------------------------------------
Reporter: Adam Alton | Owner: Adam
| Alton
Type: Bug | Status: assigned

Component: Database layer | Version: 1.11
(models, ORM) |
Severity: Release blocker | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Adam Alton):

* owner: nobody => Adam Alton
* status: new => assigned


Old description:

New description:

The offending line is:

{{{#!python
return lambda: self.default
}}}

https://github.com/adamalton/django/commit/ee6aafacfd01f2603943e8c4183805fd4a298355

--

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

Django

unread,
May 9, 2017, 9:10:07 AM5/9/17
to django-...@googlegroups.com
#28188: Field._get_default() prevents model fields from being pickled
-------------------------------------+-------------------------------------
Reporter: Adam Alton | Owner: (none)
Type: Bug | Status: new

Component: Database layer | Version: 1.11
(models, ORM) |
Severity: Release blocker | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0

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

* owner: Adam Alton => (none)
* status: assigned => new
* has_patch: 0 => 1


Comment:

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

I've made the pull request to merge into the ''stable/1.11.x'' branch
(which is what I branched from). I hope that's the right thing to do.
Let me know if it's not.

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

Django

unread,
May 11, 2017, 9:05:05 PM5/11/17
to django-...@googlegroups.com
#28188: Field._get_default() prevents model fields from being pickled
-------------------------------------+-------------------------------------
Reporter: Adam Alton | Owner: GitHub
| <noreply@…>
Type: Bug | Status: closed

Component: Database layer | Version: 1.11
(models, ORM) |
Severity: Release blocker | Resolution: fixed
Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by GitHub <noreply@…>):

* status: new => closed
* owner: (none) => GitHub <noreply@…>
* resolution: => fixed


Comment:

In [changeset:"a9874d48b1b9d91988b9f299726ec4f559fb2f75" a9874d48]:
{{{
#!CommitTicketReference repository=""
revision="a9874d48b1b9d91988b9f299726ec4f559fb2f75"
Fixed #28188 -- Fixed crash when pickling model fields.

Regression in d2a26c1a90e837777dabdf3d67ceec4d2a70fb86.

Thanks Adam Alton for the report and test, and Adam Johnson for
suggesting the fix.
}}}

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

Django

unread,
May 11, 2017, 9:17:45 PM5/11/17
to django-...@googlegroups.com
#28188: Field._get_default() prevents model fields from being pickled
-------------------------------------+-------------------------------------
Reporter: Adam Alton | Owner: GitHub
| <noreply@…>
Type: Bug | Status: closed
Component: Database layer | Version: 1.11
(models, ORM) |
Severity: Release blocker | Resolution: fixed
Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0

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

Comment (by Tim Graham <timograham@…>):

In [changeset:"74b0837bef6270a78f55878c488561f81a6339f7" 74b0837]:
{{{
#!CommitTicketReference repository=""
revision="74b0837bef6270a78f55878c488561f81a6339f7"
[1.11.x] Fixed #28188 -- Fixed crash when pickling model fields.

Regression in d2a26c1a90e837777dabdf3d67ceec4d2a70fb86.

Thanks Adam Alton for the report and test, and Adam Johnson for
suggesting the fix.

Backport of a9874d48b1b9d91988b9f299726ec4f559fb2f75 from master
}}}

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

Reply all
Reply to author
Forward
0 new messages