Code

Ticket #5524: 5524-new2.diff

File 5524-new2.diff, 7.9 KB (added by claudep, 2 years ago)

Added release notes section

Line 
1diff --git a/django/forms/forms.py b/django/forms/forms.py
2index d3f2046..5d58e7f 100644
3--- a/django/forms/forms.py
4+++ b/django/forms/forms.py
5@@ -270,8 +270,6 @@ class BaseForm(StrAndUnicode):
6         self._clean_fields()
7         self._clean_form()
8         self._post_clean()
9-        if self._errors:
10-            del self.cleaned_data
11 
12     def _clean_fields(self):
13         for name, field in self.fields.items():
14diff --git a/django/forms/models.py b/django/forms/models.py
15index b65f067..3f0deb7 100644
16--- a/django/forms/models.py
17+++ b/django/forms/models.py
18@@ -497,7 +497,7 @@ class BaseModelFormSet(BaseFormSet):
19         all_unique_checks = set()
20         all_date_checks = set()
21         for form in self.forms:
22-            if not hasattr(form, 'cleaned_data'):
23+            if not form.is_valid():
24                 continue
25             exclude = form._get_validation_exclusions()
26             unique_checks, date_checks = form.instance._get_unique_checks(exclude=exclude)
27@@ -509,9 +509,7 @@ class BaseModelFormSet(BaseFormSet):
28         for uclass, unique_check in all_unique_checks:
29             seen_data = set()
30             for form in self.forms:
31-                # if the form doesn't have cleaned_data then we ignore it,
32-                # it's already invalid
33-                if not hasattr(form, "cleaned_data"):
34+                if not form.is_valid():
35                     continue
36                 # get data for each field of each of unique_check
37                 row_data = tuple([form.cleaned_data[field] for field in unique_check if field in form.cleaned_data])
38@@ -531,9 +529,7 @@ class BaseModelFormSet(BaseFormSet):
39             seen_data = set()
40             uclass, lookup, field, unique_for = date_check
41             for form in self.forms:
42-                # if the form doesn't have cleaned_data then we ignore it,
43-                # it's already invalid
44-                if not hasattr(self, 'cleaned_data'):
45+                if not form.is_valid():
46                     continue
47                 # see if we have data for both fields
48                 if (form.cleaned_data and form.cleaned_data[field] is not None
49diff --git a/docs/ref/forms/validation.txt b/docs/ref/forms/validation.txt
50index 7657353..0f7e57f 100644
51--- a/docs/ref/forms/validation.txt
52+++ b/docs/ref/forms/validation.txt
53@@ -360,7 +360,8 @@ Secondly, once we have decided that the combined data in the two fields we are
54 considering aren't valid, we must remember to remove them from the
55 ``cleaned_data``.
56 
57-In fact, Django will currently completely wipe out the ``cleaned_data``
58-dictionary if there are any errors in the form. However, this behavior may
59-change in the future, so it's not a bad idea to clean up after yourself in the
60-first place.
61+Before 1.4, Django used to completely wipe out the ``cleaned_data``
62+dictionary if there were any errors in the form.
63+From 1.4, the ``cleaned_data`` is present even if the form doesn't validate,
64+but it contains only field values that did validate (empty dictionary if none
65+validated).
66diff --git a/docs/releases/1.4.txt b/docs/releases/1.4.txt
67index 7ffc1aa..e905631 100644
68--- a/docs/releases/1.4.txt
69+++ b/docs/releases/1.4.txt
70@@ -840,6 +840,15 @@ whose primary use is to load fixtures consisting of simple objects. Even though
71 fixtures are trusted data, for additional security, the YAML deserializer now
72 uses ``yaml.safe_load``.
73 
74+`cleaned_data` dictionary not wiped any more for invalid forms
75+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
76+
77+The ``cleaned_data`` dictionary for forms is now always present after
78+validation, regardless of the success or the failure of the validation process.
79+You should always test the success of the validation with the ``is_valid()``
80+method, and not with the presence or absence of the ``cleaned_data`` property on
81+the form.
82+
83 .. _deprecated-features-1.4:
84 
85 Features deprecated in 1.4
86diff --git a/tests/modeltests/model_forms/tests.py b/tests/modeltests/model_forms/tests.py
87index c4abdbb..f95d365 100644
88--- a/tests/modeltests/model_forms/tests.py
89+++ b/tests/modeltests/model_forms/tests.py
90@@ -637,8 +637,7 @@ class OldFormForXTests(TestCase):
91         f = BaseCategoryForm({'name': '', 'slug': 'not a slug!', 'url': 'foo'})
92         self.assertEqual(f.errors['name'], [u'This field is required.'])
93         self.assertEqual(f.errors['slug'], [u"Enter a valid 'slug' consisting of letters, numbers, underscores or hyphens."])
94-        with self.assertRaises(AttributeError):
95-            f.cleaned_data
96+        self.assertEqual(f.cleaned_data, {'url': u'foo'})
97         with self.assertRaises(ValueError):
98             f.save()
99         f = BaseCategoryForm({'name': '', 'slug': '', 'url': 'foo'})
100diff --git a/tests/regressiontests/forms/tests/forms.py b/tests/regressiontests/forms/tests/forms.py
101index 4e9cc16..4c14ca6 100644
102--- a/tests/regressiontests/forms/tests/forms.py
103+++ b/tests/regressiontests/forms/tests/forms.py
104@@ -79,11 +79,7 @@ class FormsTestCase(TestCase):
105         self.assertEqual(p.errors['last_name'], [u'This field is required.'])
106         self.assertEqual(p.errors['birthday'], [u'This field is required.'])
107         self.assertFalse(p.is_valid())
108-        try:
109-            p.cleaned_data
110-            self.fail('Attempts to access cleaned_data when validation fails should fail.')
111-        except AttributeError:
112-            pass
113+        self.assertEqual(p.cleaned_data, {})
114         self.assertEqual(str(p), """<tr><th><label for="id_first_name">First name:</label></th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="first_name" id="id_first_name" /></td></tr>
115 <tr><th><label for="id_last_name">Last name:</label></th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="last_name" id="id_last_name" /></td></tr>
116 <tr><th><label for="id_birthday">Birthday:</label></th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="birthday" id="id_birthday" /></td></tr>""")
117@@ -142,11 +138,7 @@ class FormsTestCase(TestCase):
118   * This field is required.
119 * birthday
120   * This field is required.""")
121-        try:
122-            p.cleaned_data
123-            self.fail('Attempts to access cleaned_data when validation fails should fail.')
124-        except AttributeError:
125-            pass
126+        self.assertEqual(p.cleaned_data, {'last_name': u'Lennon'})
127         self.assertEqual(p['first_name'].errors, [u'This field is required.'])
128         self.assertEqual(p['first_name'].errors.as_ul(), u'<ul class="errorlist"><li>This field is required.</li></ul>')
129         self.assertEqual(p['first_name'].errors.as_text(), u'* This field is required.')
130@@ -1672,11 +1664,7 @@ class FormsTestCase(TestCase):
131         form = SongForm(data, empty_permitted=False)
132         self.assertFalse(form.is_valid())
133         self.assertEqual(form.errors, {'name': [u'This field is required.'], 'artist': [u'This field is required.']})
134-        try:
135-            form.cleaned_data
136-            self.fail('Attempts to access cleaned_data when validation fails should fail.')
137-        except AttributeError:
138-            pass
139+        self.assertEqual(form.cleaned_data, {})
140 
141         # Now let's show what happens when empty_permitted=True and the form is empty.
142         form = SongForm(data, empty_permitted=True)
143@@ -1690,11 +1678,7 @@ class FormsTestCase(TestCase):
144         form = SongForm(data, empty_permitted=False)
145         self.assertFalse(form.is_valid())
146         self.assertEqual(form.errors, {'name': [u'This field is required.']})
147-        try:
148-            form.cleaned_data
149-            self.fail('Attempts to access cleaned_data when validation fails should fail.')
150-        except AttributeError:
151-            pass
152+        self.assertEqual(form.cleaned_data, {'artist': u'The Doors'})
153 
154         # If a field is not given in the data then None is returned for its data. Lets
155         # make sure that when checking for empty_permitted that None is treated