Browse Source

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.
Tim Graham 7 years ago
parent
commit
a9874d48b1
3 changed files with 16 additions and 1 deletions
  1. 5 1
      django/db/models/fields/__init__.py
  2. 2 0
      docs/releases/1.11.2.txt
  3. 9 0
      tests/model_fields/tests.py

+ 5 - 1
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)
 

+ 2 - 0
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`).

+ 9 - 0
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):