Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Fixed #13328 -- Added a __getstate__/__setstate__ pair to fields so t…

…hat callable default values aren't pickled. Thanks to bkonkle for the report, and Vitaly Babiy for the patch.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@12977 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit 2faa3acb4bb55f1830d517473c4bfb1616f92726 1 parent d9aaad4
@freakboy3742 freakboy3742 authored
View
1  AUTHORS
@@ -57,6 +57,7 @@ answer newbie questions, and generally made Django that much better:
David Avsajanishvili <avsd05@gmail.com>
Mike Axiak <axiak@mit.edu>
Niran Babalola <niran@niran.org>
+ Vitaly Babiy <vbabiy86@gmail.com>
Morten Bagai <m@bagai.com>
Jeff Balogh <jbalogh@mozilla.com>
Mikaël Barbero <mikael.barbero nospam at nospam free.fr>
View
14 django/db/models/fields/__init__.py
@@ -132,6 +132,19 @@ def __deepcopy__(self, memodict):
memodict[id(self)] = obj
return obj
+ def __getstate__(self):
+ "Don't try to pickle a callable default value"
+ obj_dict = self.__dict__.copy()
+ del obj_dict['default']
+ return obj_dict
+
+ def __setstate__(self, data):
+ "When unpickling, restore the callable default"
+ self.__dict__.update(data)
+
+ # Restore the default
+ self.default = self.model._meta.get_field_by_name(self.name)[0].default
+
def to_python(self, value):
"""
Converts the input value into the expected Python data type, raising
@@ -233,6 +246,7 @@ def set_attributes_from_name(self, name):
def contribute_to_class(self, cls, name):
self.set_attributes_from_name(name)
+ self.model = cls
cls._meta.add_field(self)
if self.choices:
setattr(cls, 'get_%s_display' % self.name, curry(cls._get_FIELD_display, field=self))
View
9 django/db/models/fields/proxy.py
@@ -10,7 +10,10 @@ class OrderWrt(fields.IntegerField):
A proxy for the _order database field that is used when
Meta.order_with_respect_to is specified.
"""
- name = '_order'
- attname = '_order'
- column = '_order'
+ def __init__(self, model, *args, **kwargs):
+ super(OrderWrt, self).__init__(*args, **kwargs)
+ self.model = model
+ self.attname = '_order'
+ self.column = '_order'
+ self.name = '_order'
View
4 django/db/models/options.py
@@ -104,11 +104,11 @@ def contribute_to_class(self, cls, name):
self.db_table = "%s_%s" % (self.app_label, self.module_name)
self.db_table = truncate_name(self.db_table, connection.ops.max_name_length())
-
def _prepare(self, model):
if self.order_with_respect_to:
self.order_with_respect_to = self.get_field(self.order_with_respect_to)
self.ordering = ('_order',)
+ self._order = OrderWrt(model)
else:
self.order_with_respect_to = None
@@ -331,7 +331,7 @@ def init_name_map(self):
for f, model in self.get_fields_with_model():
cache[f.name] = (f, model, True, False)
if self.order_with_respect_to:
- cache['_order'] = OrderWrt(), None, True, False
+ cache['_order'] = self._order, None, True, False
if app_cache_ready():
self._name_map = cache
return cache
View
12 tests/regressiontests/queryset_pickle/models.py
@@ -1,8 +1,20 @@
+import datetime
from django.db import models
from django.utils.translation import ugettext_lazy as _
+class Numbers(object):
+
+ @classmethod
+ def get_number(self):
+ return 2
+
class Group(models.Model):
name = models.CharField(_('name'), max_length=100)
class Event(models.Model):
group = models.ForeignKey(Group)
+
+class Happening(models.Model):
+ when = models.DateTimeField(blank=True, default=datetime.datetime.now)
+ name = models.CharField(blank=True, max_length=100, default=lambda:"test")
+ number = models.IntegerField(blank=True, default=Numbers.get_number)
View
15 tests/regressiontests/queryset_pickle/tests.py
@@ -1,8 +1,9 @@
import pickle
+import datetime
from django.test import TestCase
-from models import Group, Event
+from models import Group, Event, Happening
class PickleabilityTestCase(TestCase):
@@ -12,3 +13,15 @@ def assert_pickles(self, qs):
def test_related_field(self):
g = Group.objects.create(name="Ponies Who Own Maybachs")
self.assert_pickles(Event.objects.filter(group=g.id))
+
+ def test_datetime_callable_default_all(self):
+ self.assert_pickles(Happening.objects.all())
+
+ def test_datetime_callable_default_filter(self):
+ self.assert_pickles(Happening.objects.filter(when=datetime.datetime.now()))
+
+ def test_lambda_as_default(self):
+ self.assert_pickles(Happening.objects.filter(name="test"))
+
+ def test_callable_as_default(self):
+ self.assert_pickles(Happening.objects.filter(number=1))

0 comments on commit 2faa3ac

Please sign in to comment.
Something went wrong with that request. Please try again.