newforms: Added 'initial' parameter to Form, which lets initial data be specified dynamically
git-svn-id: http://code.djangoproject.com/svn/django/trunk@4297 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
54b8277ffb
commit
2e148d7064
|
@ -39,11 +39,12 @@ class BaseForm(StrAndUnicode):
|
|||
# class is different than Form. See the comments by the Form class for more
|
||||
# information. Any improvements to the form API should be made to *this*
|
||||
# class, not to the Form class.
|
||||
def __init__(self, data=None, auto_id='id_%s', prefix=None):
|
||||
def __init__(self, data=None, auto_id='id_%s', prefix=None, initial=None):
|
||||
self.is_bound = data is not None
|
||||
self.data = data or {}
|
||||
self.auto_id = auto_id
|
||||
self.prefix = prefix
|
||||
self.initial = initial or {}
|
||||
self.__errors = None # Stores the errors after clean() has been called.
|
||||
|
||||
def __unicode__(self):
|
||||
|
@ -218,7 +219,7 @@ class BoundField(StrAndUnicode):
|
|||
if auto_id and not attrs.has_key('id') and not widget.attrs.has_key('id'):
|
||||
attrs['id'] = auto_id
|
||||
if not self.form.is_bound:
|
||||
data = self.field.initial
|
||||
data = self.form.initial.get(self.name, self.field.initial)
|
||||
else:
|
||||
data = self.data
|
||||
return widget.render(self.html_name, data, attrs=attrs)
|
||||
|
|
|
@ -721,6 +721,53 @@ validation if a particular field's value is not given. ``initial`` values are
|
|||
The ``widget`` argument lets you specify a ``Widget`` class to use when
|
||||
rendering this ``Field``. See _`Widgets` below for more information.
|
||||
|
||||
Dynamic initial values
|
||||
----------------------
|
||||
|
||||
The ``initial`` argument to ``Field`` (explained above) lets you hard-code the
|
||||
initial value for a ``Field`` -- but what if you want to declare the initial
|
||||
value at runtime? For example, you might want to fill in a ``username`` field
|
||||
with the username of the current session.
|
||||
|
||||
To accomplish this, use the ``initial`` argument to a ``Form``. This argument,
|
||||
if given, should be a dictionary mapping field names to initial values. Only
|
||||
include the fields for which you're specifying an initial value; it's not
|
||||
necessary to include every field in your form. For example::
|
||||
|
||||
>>> class CommentForm(forms.Form):
|
||||
... name = forms.CharField()
|
||||
... url = forms.URLField()
|
||||
... comment = forms.CharField()
|
||||
>>> f = CommentForm(initial={'name': 'your username'}, auto_id=False)
|
||||
>>> print f
|
||||
<tr><th>Name:</th><td><input type="text" name="name" value="your username" /></td></tr>
|
||||
<tr><th>Url:</th><td><input type="text" name="url" /></td></tr>
|
||||
<tr><th>Comment:</th><td><input type="text" name="comment" /></td></tr>
|
||||
>>> f = CommentForm(initial={'name': 'another username'}, auto_id=False)
|
||||
>>> print f
|
||||
<tr><th>Name:</th><td><input type="text" name="name" value="another username" /></td></tr>
|
||||
<tr><th>Url:</th><td><input type="text" name="url" /></td></tr>
|
||||
<tr><th>Comment:</th><td><input type="text" name="comment" /></td></tr>
|
||||
|
||||
Just like the ``initial`` parameter to ``Field``, these values are only
|
||||
displayed for unbound forms, and they're not used as fallback values if a
|
||||
particular value isn't provided.
|
||||
|
||||
Finally, note that if a ``Field`` defines ``initial`` *and* you include
|
||||
``initial`` when instantiating the ``Form``, then the latter ``initial`` will
|
||||
have precedence. In this example, ``initial`` is provided both at the field
|
||||
level and at the form instance level, and the latter gets precedence::
|
||||
|
||||
>>> class CommentForm(forms.Form):
|
||||
... name = forms.CharField(initial='class')
|
||||
... url = forms.URLField()
|
||||
... comment = forms.CharField()
|
||||
>>> f = CommentForm(initial={'name': 'instance'}, auto_id=False)
|
||||
>>> print f
|
||||
<tr><th>Name:</th><td><input type="text" name="name" value="instance" /></td></tr>
|
||||
<tr><th>Url:</th><td><input type="text" name="url" /></td></tr>
|
||||
<tr><th>Comment:</th><td><input type="text" name="comment" /></td></tr>
|
||||
|
||||
More coming soon
|
||||
================
|
||||
|
||||
|
|
|
@ -2215,6 +2215,61 @@ validation error rather than using the initial value for 'username'.
|
|||
>>> p.is_valid()
|
||||
False
|
||||
|
||||
# Dynamic initial data ########################################################
|
||||
|
||||
The previous technique dealt with "hard-coded" initial data, but it's also
|
||||
possible to specify initial data after you've already created the Form class
|
||||
(i.e., at runtime). Use the 'initial' parameter to the Form constructor. This
|
||||
should be a dictionary containing initial values for one or more fields in the
|
||||
form, keyed by field name.
|
||||
|
||||
>>> class UserRegistration(Form):
|
||||
... username = CharField(max_length=10)
|
||||
... password = CharField(widget=PasswordInput)
|
||||
|
||||
Here, we're not submitting any data, so the initial value will be displayed.
|
||||
>>> p = UserRegistration(initial={'username': 'django'}, auto_id=False)
|
||||
>>> print p.as_ul()
|
||||
<li>Username: <input type="text" name="username" value="django" maxlength="10" /></li>
|
||||
<li>Password: <input type="password" name="password" /></li>
|
||||
>>> p = UserRegistration(initial={'username': 'stephane'}, auto_id=False)
|
||||
>>> print p.as_ul()
|
||||
<li>Username: <input type="text" name="username" value="stephane" maxlength="10" /></li>
|
||||
<li>Password: <input type="password" name="password" /></li>
|
||||
|
||||
The 'initial' parameter is meaningless if you pass data.
|
||||
>>> p = UserRegistration({}, initial={'username': 'django'}, auto_id=False)
|
||||
>>> print p.as_ul()
|
||||
<li><ul class="errorlist"><li>This field is required.</li></ul>Username: <input type="text" name="username" maxlength="10" /></li>
|
||||
<li><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /></li>
|
||||
>>> p = UserRegistration({'username': u''}, initial={'username': 'django'}, auto_id=False)
|
||||
>>> print p.as_ul()
|
||||
<li><ul class="errorlist"><li>This field is required.</li></ul>Username: <input type="text" name="username" maxlength="10" /></li>
|
||||
<li><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /></li>
|
||||
>>> p = UserRegistration({'username': u'foo'}, initial={'username': 'django'}, auto_id=False)
|
||||
>>> print p.as_ul()
|
||||
<li>Username: <input type="text" name="username" value="foo" maxlength="10" /></li>
|
||||
<li><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /></li>
|
||||
|
||||
A dynamic 'initial' value is *not* used as a fallback if data is not provided.
|
||||
In this example, we don't provide a value for 'username', and the form raises a
|
||||
validation error rather than using the initial value for 'username'.
|
||||
>>> p = UserRegistration({'password': 'secret'}, initial={'username': 'django'})
|
||||
>>> p.errors
|
||||
{'username': [u'This field is required.']}
|
||||
>>> p.is_valid()
|
||||
False
|
||||
|
||||
If a Form defines 'initial' *and* 'initial' is passed as a parameter to Form(),
|
||||
then the latter will get precedence.
|
||||
>>> class UserRegistration(Form):
|
||||
... username = CharField(max_length=10, initial='django')
|
||||
... password = CharField(widget=PasswordInput)
|
||||
>>> p = UserRegistration(initial={'username': 'babik'}, auto_id=False)
|
||||
>>> print p.as_ul()
|
||||
<li>Username: <input type="text" name="username" value="babik" maxlength="10" /></li>
|
||||
<li>Password: <input type="password" name="password" /></li>
|
||||
|
||||
# Forms with prefixes #########################################################
|
||||
|
||||
Sometimes it's necessary to have multiple forms display on the same HTML page,
|
||||
|
|
Loading…
Reference in New Issue