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):