diff options
| author | Chris Beaven <smileychris@gmail.com> | 2010-11-28 02:50:31 +0000 |
|---|---|---|
| committer | Chris Beaven <smileychris@gmail.com> | 2010-11-28 02:50:31 +0000 |
| commit | d3f5f219f5f42ac3504ed626dcb92f4ee2dc3d5f (patch) | |
| tree | 610a47472e403afeeaceaa635b2108d883ee2cc2 | |
| parent | e74edb4d53b089ec57ec4830eeba98607283a092 (diff) | |
Fixes #10427 -- Abstract the value generation of a BoundField
git-svn-id: http://code.djangoproject.com/svn/django/trunk@14734 bcc190cf-cafb-0310-a4f2-bffc1f526a37
| -rw-r--r-- | django/forms/forms.py | 26 | ||||
| -rw-r--r-- | docs/ref/forms/api.txt | 97 | ||||
| -rw-r--r-- | tests/regressiontests/forms/tests/forms.py | 15 |
3 files changed, 86 insertions, 52 deletions
diff --git a/django/forms/forms.py b/django/forms/forms.py index 0377de4767..1cf6f2a3a2 100644 --- a/django/forms/forms.py +++ b/django/forms/forms.py @@ -432,20 +432,11 @@ class BoundField(StrAndUnicode): else: attrs['id'] = self.html_initial_id - if not self.form.is_bound: - data = self.form.initial.get(self.name, self.field.initial) - if callable(data): - data = data() - else: - data = self.field.bound_data( - self.data, self.form.initial.get(self.name, self.field.initial)) - data = self.field.prepare_value(data) - if not only_initial: name = self.html_name else: name = self.html_initial_name - return widget.render(name, data, attrs=attrs) + return widget.render(name, self.value(), attrs=attrs) def as_text(self, attrs=None, **kwargs): """ @@ -470,6 +461,21 @@ class BoundField(StrAndUnicode): return self.field.widget.value_from_datadict(self.form.data, self.form.files, self.html_name) data = property(_data) + def value(self): + """ + Returns the value for this BoundField, using the initial value if + the form is not bound or the data otherwise. + """ + if not self.form.is_bound: + data = self.form.initial.get(self.name, self.field.initial) + if callable(data): + data = data() + else: + data = self.field.bound_data( + self.data, self.form.initial.get(self.name, self.field.initial) + ) + return self.field.prepare_value(data) + def label_tag(self, contents=None, attrs=None): """ Wraps the given contents in a <label>, if the field has an ID attribute. diff --git a/docs/ref/forms/api.txt b/docs/ref/forms/api.txt index 613d7544a9..5a688b6042 100644 --- a/docs/ref/forms/api.txt +++ b/docs/ref/forms/api.txt @@ -584,36 +584,29 @@ More granular output The ``as_p()``, ``as_ul()`` and ``as_table()`` methods are simply shortcuts for lazy developers -- they're not the only way a form object can be displayed. -To display the HTML for a single field in your form, use dictionary lookup -syntax using the field's name as the key, and print the resulting object:: +.. class:: BoundField - >>> f = ContactForm() - >>> print f['subject'] - <input id="id_subject" type="text" name="subject" maxlength="100" /> - >>> print f['message'] - <input type="text" name="message" id="id_message" /> - >>> print f['sender'] - <input type="text" name="sender" id="id_sender" /> - >>> print f['cc_myself'] - <input type="checkbox" name="cc_myself" id="id_cc_myself" /> + Used to display HTML or access attributes for a single field of a + :class:`Form` instance. + + The :meth:`__unicode__` and :meth:`__str__` methods of this object displays + the HTML for this field. -Call ``str()`` or ``unicode()`` on the field to get its rendered HTML as a -string or Unicode object, respectively:: +To retrieve a single ``BoundField``, use dictionary lookup syntax on your form +using the field's name as the key:: - >>> str(f['subject']) - '<input id="id_subject" type="text" name="subject" maxlength="100" />' - >>> unicode(f['subject']) - u'<input id="id_subject" type="text" name="subject" maxlength="100" />' + >>> form = ContactForm() + >>> print form['subject'] + <input id="id_subject" type="text" name="subject" maxlength="100" /> -Form objects define a custom ``__iter__()`` method, which allows you to loop -through their fields:: +To retrieve all ``BoundField`` objects, iterate the form:: - >>> f = ContactForm() - >>> for field in f: print field - <input id="id_subject" type="text" name="subject" maxlength="100" /> - <input type="text" name="message" id="id_message" /> - <input type="text" name="sender" id="id_sender" /> - <input type="checkbox" name="cc_myself" id="id_cc_myself" /> + >>> form = ContactForm() + >>> for boundfield in form: print boundfield + <input id="id_subject" type="text" name="subject" maxlength="100" /> + <input type="text" name="message" id="id_message" /> + <input type="text" name="sender" id="id_sender" /> + <input type="checkbox" name="cc_myself" id="id_cc_myself" /> The field-specific output honors the form object's ``auto_id`` setting:: @@ -624,26 +617,31 @@ The field-specific output honors the form object's ``auto_id`` setting:: >>> print f['message'] <input type="text" name="message" id="id_message" /> -For a field's list of errors, access the field's ``errors`` attribute. This -is a list-like object that is displayed as an HTML ``<ul class="errorlist">`` -when printed:: +For a field's list of errors, access the field's ``errors`` attribute. - >>> data = {'subject': 'hi', 'message': '', 'sender': '', 'cc_myself': ''} - >>> f = ContactForm(data, auto_id=False) - >>> print f['message'] - <input type="text" name="message" /> - >>> f['message'].errors - [u'This field is required.'] - >>> print f['message'].errors - <ul class="errorlist"><li>This field is required.</li></ul> - >>> f['subject'].errors - [] - >>> print f['subject'].errors +.. attribute:: BoundField.errors - >>> str(f['subject'].errors) - '' + A list-like object that is displayed as an HTML ``<ul class="errorlist">`` + when printed:: -.. versionadded:: 1.2 + >>> data = {'subject': 'hi', 'message': '', 'sender': '', 'cc_myself': ''} + >>> f = ContactForm(data, auto_id=False) + >>> print f['message'] + <input type="text" name="message" /> + >>> f['message'].errors + [u'This field is required.'] + >>> print f['message'].errors + <ul class="errorlist"><li>This field is required.</li></ul> + >>> f['subject'].errors + [] + >>> print f['subject'].errors + + >>> str(f['subject'].errors) + '' + +.. method:: BoundField.css_classes() + + .. versionadded:: 1.2 When you use Django's rendering shortcuts, CSS classes are used to indicate required form fields or fields that contain errors. If you're @@ -662,6 +660,21 @@ those classes as an argument:: >>> f['message'].css_classes('foo bar') 'foo bar required' +.. method:: BoundField.values() + + .. versionadded:: 1.3 + +Use this method to render the raw value of this field as it would be rendered +by a ``Widget``:: + + >>> initial = {'subject': 'welcome'} + >>> unbound_form = ContactForm(initial=initial) + >>> bound_form = ContactForm(data, initial=initial) + >>> print unbound_form['subject'].value + welcome + >>> print bound_form['subject'].value + hi + .. _binding-uploaded-files: Binding uploaded files to a form diff --git a/tests/regressiontests/forms/tests/forms.py b/tests/regressiontests/forms/tests/forms.py index b52a0537ee..91a7472cd1 100644 --- a/tests/regressiontests/forms/tests/forms.py +++ b/tests/regressiontests/forms/tests/forms.py @@ -1151,6 +1151,21 @@ class FormsTestCase(TestCase): <option value="w">whiz</option> </select></li>""") + def test_boundfield_values(self): + # It's possible to get to the value which would be used for rendering + # the widget for a field by using the BoundField's value method. + + class UserRegistration(Form): + username = CharField(max_length=10, initial='djangonaut') + password = CharField(widget=PasswordInput) + + unbound = UserRegistration() + bound = UserRegistration({'password': 'foo'}) + self.assertEqual(bound['username'].value(), None) + self.assertEqual(unbound['username'].value(), 'djangonaut') + self.assertEqual(bound['password'].value(), 'foo') + self.assertEqual(unbound['password'].value(), None) + def test_help_text(self): # You can specify descriptive text for a field by using the 'help_text' argument) class UserRegistration(Form): |
