From 8714403614c4dfa37e806db4a6708b8a91a827a4 Mon Sep 17 00:00:00 2001 From: Claude Paroz Date: Wed, 4 Mar 2015 20:19:02 +0100 Subject: [PATCH] Fixed #24428 -- Fixed has_changed for fields with coercion Thanks Carsten Fuchs for the report. --- django/forms/fields.py | 1 + tests/forms_tests/tests/test_fields.py | 1 + tests/model_forms/models.py | 17 +++++++++++ tests/model_forms/tests.py | 40 ++++++++++++++++++++++++-- 4 files changed, 57 insertions(+), 2 deletions(-) diff --git a/django/forms/fields.py b/django/forms/fields.py index 44bbfd8e6f..57d6a755c6 100644 --- a/django/forms/fields.py +++ b/django/forms/fields.py @@ -195,6 +195,7 @@ class Field(six.with_metaclass(RenameFieldMethods, object)): data = self.to_python(data) if hasattr(self, '_coerce'): data = self._coerce(data) + initial_value = self._coerce(initial_value) except ValidationError: return True data_value = data if data is not None else '' diff --git a/tests/forms_tests/tests/test_fields.py b/tests/forms_tests/tests/test_fields.py index b4d922f6b1..faedd1783c 100644 --- a/tests/forms_tests/tests/test_fields.py +++ b/tests/forms_tests/tests/test_fields.py @@ -1082,6 +1082,7 @@ class FieldsTests(SimpleTestCase): f = TypedChoiceField(choices=[(1, "+1"), (-1, "-1")], coerce=int, required=True) self.assertFalse(f.has_changed(None, '')) self.assertFalse(f.has_changed(1, '1')) + self.assertFalse(f.has_changed('1', '1')) def test_typedchoicefield_special_coerce(self): """ diff --git a/tests/model_forms/models.py b/tests/model_forms/models.py index 2cfe523175..08b0c96ac5 100644 --- a/tests/model_forms/models.py +++ b/tests/model_forms/models.py @@ -106,6 +106,23 @@ class Publication(models.Model): return self.title +def default_mode(): + return 'di' + + +def default_category(): + return 3 + + +class PublicationDefaults(models.Model): + MODE_CHOICES = (('di', 'direct'), ('de', 'delayed')) + CATEGORY_CHOICES = ((1, 'Games'), (2, 'Comics'), (3, 'Novel')) + title = models.CharField(max_length=30) + date_published = models.DateField(default=datetime.date.today) + mode = models.CharField(max_length=2, choices=MODE_CHOICES, default=default_mode) + category = models.IntegerField(choices=CATEGORY_CHOICES, default=default_category) + + class Author(models.Model): publication = models.OneToOneField(Publication, null=True, blank=True) full_name = models.CharField(max_length=255) diff --git a/tests/model_forms/tests.py b/tests/model_forms/tests.py index fcc9d269ec..7ba9efefbc 100644 --- a/tests/model_forms/tests.py +++ b/tests/model_forms/tests.py @@ -28,8 +28,9 @@ from .models import ( CustomErrorMessage, CustomFF, CustomFieldForExclusionModel, DateTimePost, DerivedBook, DerivedPost, Document, ExplicitPK, FilePathModel, FlexibleDatePost, Homepage, ImprovedArticle, ImprovedArticleWithParentLink, - Inventory, Person, Photo, Post, Price, Product, Publication, Student, - StumpJoke, TextFile, Triple, Writer, WriterProfile, test_images, + Inventory, Person, Photo, Post, Price, Product, Publication, + PublicationDefaults, Student, StumpJoke, TextFile, Triple, Writer, + WriterProfile, test_images, ) if test_images: @@ -2282,6 +2283,41 @@ class OtherModelFormTests(TestCase):

""" % {'blue_pk': colour.pk}) + def test_callable_field_default(self): + class PublicationDefaultsForm(forms.ModelForm): + class Meta: + model = PublicationDefaults + fields = '__all__' + + form = PublicationDefaultsForm() + self.assertHTMLEqual( + form.as_p(), + """

+

+ +

+

+

+

+ """ + ) + empty_data = { + 'title': '', + 'date_published': '2015-03-04', + 'initial-date_published': '2015-03-04', + 'mode': 'di', + 'initial-mode': 'di', + 'category': '3', + 'initial-category': '3', + } + bound_form = PublicationDefaultsForm(empty_data) + self.assertFalse(bound_form.has_changed()) + class ModelFormCustomErrorTests(TestCase): def test_custom_error_messages(self):