diff --git a/django/contrib/formtools/preview.py b/django/contrib/formtools/preview.py index daecba7928..351d991762 100644 --- a/django/contrib/formtools/preview.py +++ b/django/contrib/formtools/preview.py @@ -24,7 +24,7 @@ Usage Subclass FormPreview and define a done() method: - def done(self, request, clean_data): + def done(self, request, cleaned_data): # ... This method takes an HttpRequest object and a dictionary of the form data after @@ -113,7 +113,7 @@ class FormPreview(object): if f.is_valid(): if self.security_hash(request, f) != request.POST.get(self.unused_name('hash')): return self.failed_hash(request) # Security hash failed. - return self.done(request, f.clean_data) + return self.done(request, f.cleaned_data) else: return render_to_response(self.form_template, {'form': f, 'stage_field': self.unused_name('stage'), 'state': self.state}, @@ -160,6 +160,9 @@ class FormPreview(object): # METHODS SUBCLASSES MUST OVERRIDE ######################################## - def done(self, request, clean_data): - "Does something with the clean_data and returns an HttpResponseRedirect." + def done(self, request, cleaned_data): + """ + Does something with the cleaned_data and returns an + HttpResponseRedirect. + """ raise NotImplementedError('You must define a done() method on your %s subclass.' % self.__class__.__name__) diff --git a/django/newforms/forms.py b/django/newforms/forms.py index f624e005e9..0923cd50ea 100644 --- a/django/newforms/forms.py +++ b/django/newforms/forms.py @@ -169,13 +169,13 @@ class BaseForm(StrAndUnicode): def full_clean(self): """ - Cleans all of self.data and populates self.__errors and self.clean_data. + Cleans all of self.data and populates self.__errors and self.cleaned_data. """ errors = ErrorDict() if not self.is_bound: # Stop further processing. self.__errors = errors return - self.clean_data = {} + self.cleaned_data = {} for name, field in self.fields.items(): # value_from_datadict() gets the data from the dictionary. # Each widget type knows how to retrieve its own data, because some @@ -183,18 +183,18 @@ class BaseForm(StrAndUnicode): value = field.widget.value_from_datadict(self.data, self.add_prefix(name)) try: value = field.clean(value) - self.clean_data[name] = value - if hasattr(self, 'do_clean_%s' % name): - value = getattr(self, 'do_clean_%s' % name)() - self.clean_data[name] = value + self.cleaned_data[name] = value + if hasattr(self, 'clean_%s' % name): + value = getattr(self, 'clean_%s' % name)() + self.cleaned_data[name] = value except ValidationError, e: errors[name] = e.messages try: - self.clean_data = self.clean() + self.cleaned_data = self.clean() except ValidationError, e: errors[NON_FIELD_ERRORS] = e.messages if errors: - delattr(self, 'clean_data') + delattr(self, 'cleaned_data') self.__errors = errors def clean(self): @@ -204,7 +204,7 @@ class BaseForm(StrAndUnicode): not be associated with a particular field; it will have a special-case association with the field named '__all__'. """ - return self.clean_data + return self.cleaned_data class Form(BaseForm): "A collection of Fields, plus their associated data." diff --git a/django/newforms/models.py b/django/newforms/models.py index ea99ca9ea0..9d7d027031 100644 --- a/django/newforms/models.py +++ b/django/newforms/models.py @@ -14,7 +14,7 @@ __all__ = ('save_instance', 'form_for_model', 'form_for_instance', 'form_for_fie def save_instance(form, instance, fields=None, fail_message='saved', commit=True): """ - Saves bound Form ``form``'s clean_data into model instance ``instance``. + Saves bound Form ``form``'s cleaned_data into model instance ``instance``. Assumes ``form`` has a field for every non-AutoField database field in ``instance``. If commit=True, then the changes to ``instance`` will be @@ -24,20 +24,20 @@ def save_instance(form, instance, fields=None, fail_message='saved', commit=True opts = instance.__class__._meta if form.errors: raise ValueError("The %s could not be %s because the data didn't validate." % (opts.object_name, fail_message)) - clean_data = form.clean_data + cleaned_data = form.cleaned_data for f in opts.fields: - if not f.editable or isinstance(f, models.AutoField) or not f.name in clean_data: + if not f.editable or isinstance(f, models.AutoField) or not f.name in cleaned_data: continue if fields and f.name not in fields: continue - setattr(instance, f.name, clean_data[f.name]) + setattr(instance, f.name, cleaned_data[f.name]) if commit: instance.save() for f in opts.many_to_many: if fields and f.name not in fields: continue - if f.name in clean_data: - setattr(instance, f.attname, clean_data[f.name]) + if f.name in cleaned_data: + setattr(instance, f.attname, cleaned_data[f.name]) # GOTCHA: If many-to-many data is given and commit=False, the many-to-many # data will be lost. This happens because a many-to-many options cannot be # set on an object until after it's saved. Maybe we should raise an diff --git a/docs/newforms.txt b/docs/newforms.txt index 7c861ed405..ed43670960 100644 --- a/docs/newforms.txt +++ b/docs/newforms.txt @@ -230,7 +230,7 @@ object. Regardless of whether you pass it a string in the format it's valid. Once you've created a ``Form`` instance with a set of data and validated it, -you can access the clean data via the ``clean_data`` attribute of the ``Form`` +you can access the clean data via the ``cleaned_data`` attribute of the ``Form`` object:: >>> data = {'subject': 'hello', @@ -240,7 +240,7 @@ object:: >>> f = ContactForm(data) >>> f.is_valid() True - >>> f.clean_data + >>> f.cleaned_data {'cc_myself': True, 'message': u'Hi there', 'sender': u'foo@example.com', 'subject': u'hello'} Note that any text-based field -- such as ``CharField`` or ``EmailField`` -- @@ -248,7 +248,7 @@ always cleans the input into a Unicode string. We'll cover the encoding implications later in this document. If your data does *not* validate, your ``Form`` instance will not have a -``clean_data`` attribute:: +``cleaned_data`` attribute:: >>> data = {'subject': '', ... 'message': 'Hi there', @@ -257,15 +257,15 @@ If your data does *not* validate, your ``Form`` instance will not have a >>> f = ContactForm(data) >>> f.is_valid() False - >>> f.clean_data + >>> f.cleaned_data Traceback (most recent call last): ... - AttributeError: 'ContactForm' object has no attribute 'clean_data' + AttributeError: 'ContactForm' object has no attribute 'cleaned_data' -``clean_data`` will always *only* contain a key for fields defined in the +``cleaned_data`` will always *only* contain a key for fields defined in the ``Form``, even if you pass extra data when you define the ``Form``. In this example, we pass a bunch of extra fields to the ``ContactForm`` constructor, -but ``clean_data`` contains only the form's fields:: +but ``cleaned_data`` contains only the form's fields:: >>> data = {'subject': 'hello', ... 'message': 'Hi there', @@ -277,13 +277,13 @@ but ``clean_data`` contains only the form's fields:: >>> f = ContactForm(data) >>> f.is_valid() True - >>> f.clean_data # Doesn't contain extra_field_1, etc. + >>> f.cleaned_data # Doesn't contain extra_field_1, etc. {'cc_myself': True, 'message': u'Hi there', 'sender': u'foo@example.com', 'subject': u'hello'} -``clean_data`` will include a key and value for *all* fields defined in the +``cleaned_data`` will include a key and value for *all* fields defined in the ``Form``, even if the data didn't include a value for fields that are not required. In this example, the data dictionary doesn't include a value for the -``nick_name`` field, but ``clean_data`` includes it, with an empty value:: +``nick_name`` field, but ``cleaned_data`` includes it, with an empty value:: >>> class OptionalPersonForm(Form): ... first_name = CharField() @@ -293,10 +293,10 @@ required. In this example, the data dictionary doesn't include a value for the >>> f = OptionalPersonForm(data) >>> f.is_valid() True - >>> f.clean_data + >>> f.cleaned_data {'nick_name': u'', 'first_name': u'John', 'last_name': u'Lennon'} -In this above example, the ``clean_data`` value for ``nick_name`` is set to an +In this above example, the ``cleaned_data`` value for ``nick_name`` is set to an empty string, because ``nick_name`` is ``CharField``, and ``CharField``\s treat empty values as an empty string. Each field type knows what its "blank" value is -- e.g., for ``DateField``, it's ``None`` instead of the empty string. @@ -308,10 +308,10 @@ It's meaningless to request "clean" data in a form with no data, but, for the record, here's what happens with unbound forms:: >>> f = ContactForm() - >>> f.clean_data + >>> f.cleaned_data Traceback (most recent call last): ... - AttributeError: 'ContactForm' object has no attribute 'clean_data' + AttributeError: 'ContactForm' object has no attribute 'cleaned_data' Outputting forms as HTML ------------------------ diff --git a/tests/modeltests/model_forms/models.py b/tests/modeltests/model_forms/models.py index e78f5f7bd7..6ffd4d1bce 100644 --- a/tests/modeltests/model_forms/models.py +++ b/tests/modeltests/model_forms/models.py @@ -18,7 +18,7 @@ other Form, with one additional method: save(). The save() method updates the model instance. It also takes a commit=True parameter. The function django.newforms.save_instance() takes a bound form instance and a -model instance and saves the form's clean_data into the instance. It also takes +model instance and saves the form's cleaned_data into the instance. It also takes a commit=True parameter. """ @@ -94,7 +94,7 @@ __test__ = {'API_TESTS': """ >>> f = CategoryForm({'name': 'Entertainment', 'url': 'entertainment'}) >>> f.is_valid() True ->>> f.clean_data +>>> f.cleaned_data {'url': u'entertainment', 'name': u'Entertainment'} >>> obj = f.save() >>> obj @@ -105,7 +105,7 @@ True >>> f = CategoryForm({'name': "It's a test", 'url': 'test'}) >>> f.is_valid() True ->>> f.clean_data +>>> f.cleaned_data {'url': u'test', 'name': u"It's a test"} >>> obj = f.save() >>> obj @@ -119,7 +119,7 @@ save() on the resulting model instance. >>> f = CategoryForm({'name': 'Third test', 'url': 'third'}) >>> f.is_valid() True ->>> f.clean_data +>>> f.cleaned_data {'url': u'third', 'name': u'Third test'} >>> obj = f.save(commit=False) >>> obj @@ -134,10 +134,10 @@ If you call save() with invalid data, you'll get a ValueError. >>> f = CategoryForm({'name': '', 'url': 'foo'}) >>> f.errors {'name': [u'This field is required.']} ->>> f.clean_data +>>> f.cleaned_data Traceback (most recent call last): ... -AttributeError: 'CategoryForm' object has no attribute 'clean_data' +AttributeError: 'CategoryForm' object has no attribute 'cleaned_data' >>> f.save() Traceback (most recent call last): ... @@ -524,6 +524,6 @@ ValidationError: [u'Select a valid choice. 10 is not one of the available choice >>> f = PhoneNumberForm({'phone': '(312) 555-1212', 'description': 'Assistance'}) >>> f.is_valid() True ->>> f.clean_data +>>> f.cleaned_data {'phone': u'312-555-1212', 'description': u'Assistance'} """} diff --git a/tests/regressiontests/forms/regressions.py b/tests/regressiontests/forms/regressions.py index 789ac81715..5fe057b5d8 100644 --- a/tests/regressiontests/forms/regressions.py +++ b/tests/regressiontests/forms/regressions.py @@ -46,6 +46,6 @@ doesn't come back. >>> f = DataForm({'data': 'xyzzy'}) >>> f.is_valid() True ->>> f.clean_data +>>> f.cleaned_data {'data': u'xyzzy'} """ diff --git a/tests/regressiontests/forms/tests.py b/tests/regressiontests/forms/tests.py index 82be58dd0c..5afa3d198d 100644 --- a/tests/regressiontests/forms/tests.py +++ b/tests/regressiontests/forms/tests.py @@ -1774,7 +1774,7 @@ True u'' >>> p.errors.as_text() u'' ->>> p.clean_data +>>> p.cleaned_data {'first_name': u'John', 'last_name': u'Lennon', 'birthday': datetime.date(1940, 10, 9)} >>> print p['first_name'] <input type="text" name="first_name" value="John" id="id_first_name" /> @@ -1810,10 +1810,10 @@ True {'first_name': [u'This field is required.'], 'last_name': [u'This field is required.'], 'birthday': [u'This field is required.']} >>> p.is_valid() False ->>> p.clean_data +>>> p.cleaned_data Traceback (most recent call last): ... -AttributeError: 'Person' object has no attribute 'clean_data' +AttributeError: 'Person' object has no attribute 'cleaned_data' >>> print 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> <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> @@ -1844,10 +1844,10 @@ False {} >>> p.is_valid() False ->>> p.clean_data +>>> p.cleaned_data Traceback (most recent call last): ... -AttributeError: 'Person' object has no attribute 'clean_data' +AttributeError: 'Person' object has no attribute 'cleaned_data' >>> print p <tr><th><label for="id_first_name">First name:</label></th><td><input type="text" name="first_name" id="id_first_name" /></td></tr> <tr><th><label for="id_last_name">Last name:</label></th><td><input type="text" name="last_name" id="id_last_name" /></td></tr> @@ -1886,10 +1886,10 @@ u'<ul class="errorlist"><li>first_name<ul class="errorlist"><li>This field is re * This field is required. * birthday * This field is required. ->>> p.clean_data +>>> p.cleaned_data Traceback (most recent call last): ... -AttributeError: 'Person' object has no attribute 'clean_data' +AttributeError: 'Person' object has no attribute 'cleaned_data' >>> p['first_name'].errors [u'This field is required.'] >>> p['first_name'].errors.as_ul() @@ -1905,21 +1905,21 @@ u'* This field is required.' >>> print p['birthday'] <input type="text" name="birthday" id="id_birthday" /> -clean_data will always *only* contain a key for fields defined in the +cleaned_data will always *only* contain a key for fields defined in the Form, even if you pass extra data when you define the Form. In this example, we pass a bunch of extra fields to the form constructor, -but clean_data contains only the form's fields. +but cleaned_data contains only the form's fields. >>> data = {'first_name': u'John', 'last_name': u'Lennon', 'birthday': u'1940-10-9', 'extra1': 'hello', 'extra2': 'hello'} >>> p = Person(data) >>> p.is_valid() True ->>> p.clean_data +>>> p.cleaned_data {'first_name': u'John', 'last_name': u'Lennon', 'birthday': datetime.date(1940, 10, 9)} -clean_data will include a key and value for *all* fields defined in the Form, +cleaned_data will include a key and value for *all* fields defined in the Form, even if the Form's data didn't include a value for fields that are not required. In this example, the data dictionary doesn't include a value for the -"nick_name" field, but clean_data includes it. For CharFields, it's set to the +"nick_name" field, but cleaned_data includes it. For CharFields, it's set to the empty string. >>> class OptionalPersonForm(Form): ... first_name = CharField() @@ -1929,7 +1929,7 @@ empty string. >>> f = OptionalPersonForm(data) >>> f.is_valid() True ->>> f.clean_data +>>> f.cleaned_data {'nick_name': u'', 'first_name': u'John', 'last_name': u'Lennon'} For DateFields, it's set to None. @@ -1941,7 +1941,7 @@ For DateFields, it's set to None. >>> f = OptionalPersonForm(data) >>> f.is_valid() True ->>> f.clean_data +>>> f.cleaned_data {'birth_date': None, 'first_name': u'John', 'last_name': u'Lennon'} "auto_id" tells the Form to add an "id" attribute to each form element. @@ -2292,19 +2292,19 @@ returns a list of input. >>> f = SongForm({'name': 'Yesterday', 'composers': ['J']}, auto_id=False) >>> f.errors {} ->>> f.clean_data +>>> f.cleaned_data {'composers': [u'J'], 'name': u'Yesterday'} >>> f = SongForm({'name': 'Yesterday', 'composers': ['J', 'P']}, auto_id=False) >>> f.errors {} ->>> f.clean_data +>>> f.cleaned_data {'composers': [u'J', u'P'], 'name': u'Yesterday'} Validation errors are HTML-escaped when output as HTML. >>> class EscapingForm(Form): ... special_name = CharField() -... def do_clean_special_name(self): -... raise ValidationError("Something's wrong with '%s'" % self.clean_data['special_name']) +... def clean_special_name(self): +... raise ValidationError("Something's wrong with '%s'" % self.cleaned_data['special_name']) >>> f = EscapingForm({'special_name': "Nothing to escape"}, auto_id=False) >>> print f @@ -2319,17 +2319,17 @@ There are a couple of ways to do multiple-field validation. If you want the validation message to be associated with a particular field, implement the clean_XXX() method on the Form, where XXX is the field name. As in Field.clean(), the clean_XXX() method should return the cleaned value. In the -clean_XXX() method, you have access to self.clean_data, which is a dictionary +clean_XXX() method, you have access to self.cleaned_data, which is a dictionary of all the data that has been cleaned *so far*, in order by the fields, including the current field (e.g., the field XXX if you're in clean_XXX()). >>> class UserRegistration(Form): ... username = CharField(max_length=10) ... password1 = CharField(widget=PasswordInput) ... password2 = CharField(widget=PasswordInput) -... def do_clean_password2(self): -... if self.clean_data.get('password1') and self.clean_data.get('password2') and self.clean_data['password1'] != self.clean_data['password2']: +... def clean_password2(self): +... if self.cleaned_data.get('password1') and self.cleaned_data.get('password2') and self.cleaned_data['password1'] != self.cleaned_data['password2']: ... raise ValidationError(u'Please make sure your passwords match.') -... return self.clean_data['password2'] +... return self.cleaned_data['password2'] >>> f = UserRegistration(auto_id=False) >>> f.errors {} @@ -2342,14 +2342,14 @@ including the current field (e.g., the field XXX if you're in clean_XXX()). >>> f = UserRegistration({'username': 'adrian', 'password1': 'foo', 'password2': 'foo'}, auto_id=False) >>> f.errors {} ->>> f.clean_data +>>> f.cleaned_data {'username': u'adrian', 'password1': u'foo', 'password2': u'foo'} Another way of doing multiple-field validation is by implementing the Form's clean() method. If you do this, any ValidationError raised by that method will not be associated with a particular field; it will have a special-case association with the field named '__all__'. -Note that in Form.clean(), you have access to self.clean_data, a dictionary of +Note that in Form.clean(), you have access to self.cleaned_data, a dictionary of all the fields/values that have *not* raised a ValidationError. Also note Form.clean() is required to return a dictionary of all clean data. >>> class UserRegistration(Form): @@ -2357,9 +2357,9 @@ Form.clean() is required to return a dictionary of all clean data. ... password1 = CharField(widget=PasswordInput) ... password2 = CharField(widget=PasswordInput) ... def clean(self): -... if self.clean_data.get('password1') and self.clean_data.get('password2') and self.clean_data['password1'] != self.clean_data['password2']: +... if self.cleaned_data.get('password1') and self.cleaned_data.get('password2') and self.cleaned_data['password1'] != self.cleaned_data['password2']: ... raise ValidationError(u'Please make sure your passwords match.') -... return self.clean_data +... return self.cleaned_data >>> f = UserRegistration(auto_id=False) >>> f.errors {} @@ -2386,7 +2386,7 @@ Form.clean() is required to return a dictionary of all clean data. >>> f = UserRegistration({'username': 'adrian', 'password1': 'foo', 'password2': 'foo'}, auto_id=False) >>> f.errors {} ->>> f.clean_data +>>> f.cleaned_data {'username': u'adrian', 'password1': u'foo', 'password2': u'foo'} # Dynamic construction ######################################################## @@ -2954,7 +2954,7 @@ actual field name. {} >>> p.is_valid() True ->>> p.clean_data +>>> p.cleaned_data {'first_name': u'John', 'last_name': u'Lennon', 'birthday': datetime.date(1940, 10, 9)} Let's try submitting some bad data to make sure form.errors and field.errors @@ -2998,12 +2998,12 @@ of the same form. >>> p1 = Person(data, prefix='person1') >>> p1.is_valid() True ->>> p1.clean_data +>>> p1.cleaned_data {'first_name': u'John', 'last_name': u'Lennon', 'birthday': datetime.date(1940, 10, 9)} >>> p2 = Person(data, prefix='person2') >>> p2.is_valid() True ->>> p2.clean_data +>>> p2.cleaned_data {'first_name': u'Jim', 'last_name': u'Morrison', 'birthday': datetime.date(1943, 12, 8)} By default, forms append a hyphen between the prefix and the field name, but a @@ -3029,7 +3029,7 @@ self.prefix. >>> p = Person(data, prefix='foo') >>> p.is_valid() True ->>> p.clean_data +>>> p.cleaned_data {'first_name': u'John', 'last_name': u'Lennon', 'birthday': datetime.date(1940, 10, 9)} # Forms with NullBooleanFields ################################################ @@ -3091,16 +3091,16 @@ is different than its data. This is handled transparently, though. ... password1 = CharField(widget=PasswordInput) ... password2 = CharField(widget=PasswordInput) ... def clean(self): -... if self.clean_data.get('password1') and self.clean_data.get('password2') and self.clean_data['password1'] != self.clean_data['password2']: +... if self.cleaned_data.get('password1') and self.cleaned_data.get('password2') and self.cleaned_data['password1'] != self.cleaned_data['password2']: ... raise ValidationError(u'Please make sure your passwords match.') -... return self.clean_data +... return self.cleaned_data >>> def my_function(method, post_data): ... if method == 'POST': ... form = UserRegistration(post_data, auto_id=False) ... else: ... form = UserRegistration(auto_id=False) ... if form.is_valid(): -... return 'VALID: %r' % form.clean_data +... return 'VALID: %r' % form.cleaned_data ... t = Template('<form action="" method="post">\n<table>\n{{ form }}\n</table>\n<input type="submit" />\n</form>') ... return t.render(Context({'form': form})) @@ -3138,9 +3138,9 @@ VALID: {'username': u'adrian', 'password1': u'secret', 'password2': u'secret'} ... password1 = CharField(widget=PasswordInput) ... password2 = CharField(widget=PasswordInput) ... def clean(self): -... if self.clean_data.get('password1') and self.clean_data.get('password2') and self.clean_data['password1'] != self.clean_data['password2']: +... if self.cleaned_data.get('password1') and self.cleaned_data.get('password2') and self.cleaned_data['password1'] != self.cleaned_data['password2']: ... raise ValidationError(u'Please make sure your passwords match.') -... return self.clean_data +... return self.cleaned_data You have full flexibility in displaying form fields in a template. Just pass a Form instance to the template, and use "dot" access to refer to individual @@ -3490,7 +3490,7 @@ ValidationError: [u'This field is required.'] </select> <input type="text" name="field1_2_0" value="2007-04-25" id="id_field1_2_0" /><input type="text" name="field1_2_1" value="06:24:00" id="id_field1_2_1" /></td></tr> ->>> f.clean_data +>>> f.cleaned_data {'field1': u'some text,JP,2007-04-25 06:24:00'} #################################