[1.11.x] Fixed #28188 -- Fixed crash when pickling model fields.

Regression in d2a26c1a90.

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

Backport of a9874d48b1 from master
This commit is contained in:
Tim Graham 2017-05-11 21:04:52 -04:00
parent 643413f654
commit 74b0837bef
3 changed files with 16 additions and 1 deletions

View File

@ -514,7 +514,11 @@ class Field(RegisterLookupMixin):
# instance. The code below will create a new empty instance of
# class self.__class__, then update its dict with self.__dict__
# values - so, this is very close to normal pickle.
return _empty, (self.__class__,), self.__dict__
state = self.__dict__.copy()
# The _get_default cached_property can't be pickled due to lambda
# usage.
state.pop('_get_default', None)
return _empty, (self.__class__,), state
return _load_field, (self.model._meta.app_label, self.model._meta.object_name,
self.name)

View File

@ -18,3 +18,5 @@ Bugfixes
* Fixed ``django.utils.http.is_safe_url()`` crash on invalid IPv6 URLs
(:ticket:`28142`).
* Fixed regression causing pickling of model fields to crash (:ticket:`28188`).

View File

@ -1,3 +1,5 @@
import pickle
from django import forms
from django.db import models
from django.test import SimpleTestCase, TestCase
@ -76,6 +78,13 @@ class BasicFieldTests(TestCase):
self.assertIsNotNone(f1)
self.assertNotIn(f2, (None, 1, ''))
def test_field_instance_is_picklable(self):
"""Field instances can be pickled."""
field = models.Field(max_length=100, default='a string')
# Must be picklable with this cached property populated (#28188).
field._get_default
pickle.dumps(field)
class ChoicesTests(SimpleTestCase):