summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Graham <timograham@gmail.com>2017-05-11 21:04:52 -0400
committerTim Graham <timograham@gmail.com>2017-05-11 21:05:05 -0400
commit74b0837bef6270a78f55878c488561f81a6339f7 (patch)
treec6952387eab3c754dab91ab5b2e5149724f70934
parent643413f654d52ca4d7bf6d9402ff9ca24d2ea635 (diff)
[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
-rw-r--r--django/db/models/fields/__init__.py6
-rw-r--r--docs/releases/1.11.2.txt2
-rw-r--r--tests/model_fields/tests.py9
3 files changed, 16 insertions, 1 deletions
diff --git a/django/db/models/fields/__init__.py b/django/db/models/fields/__init__.py
index 0af100efd9..8d40c77345 100644
--- a/django/db/models/fields/__init__.py
+++ b/django/db/models/fields/__init__.py
@@ -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)
diff --git a/docs/releases/1.11.2.txt b/docs/releases/1.11.2.txt
index fd6b7083e9..558b3e40c3 100644
--- a/docs/releases/1.11.2.txt
+++ b/docs/releases/1.11.2.txt
@@ -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`).
diff --git a/tests/model_fields/tests.py b/tests/model_fields/tests.py
index a9c9794a3c..00f8338128 100644
--- a/tests/model_fields/tests.py
+++ b/tests/model_fields/tests.py
@@ -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):