Kaydet (Commit) 2e148d70 authored tarafından Adrian Holovaty's avatar Adrian Holovaty

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
üst 54b8277f
...@@ -39,11 +39,12 @@ class BaseForm(StrAndUnicode): ...@@ -39,11 +39,12 @@ class BaseForm(StrAndUnicode):
# class is different than Form. See the comments by the Form class for more # 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* # information. Any improvements to the form API should be made to *this*
# class, not to the Form class. # 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.is_bound = data is not None
self.data = data or {} self.data = data or {}
self.auto_id = auto_id self.auto_id = auto_id
self.prefix = prefix self.prefix = prefix
self.initial = initial or {}
self.__errors = None # Stores the errors after clean() has been called. self.__errors = None # Stores the errors after clean() has been called.
def __unicode__(self): def __unicode__(self):
...@@ -218,7 +219,7 @@ class BoundField(StrAndUnicode): ...@@ -218,7 +219,7 @@ class BoundField(StrAndUnicode):
if auto_id and not attrs.has_key('id') and not widget.attrs.has_key('id'): if auto_id and not attrs.has_key('id') and not widget.attrs.has_key('id'):
attrs['id'] = auto_id attrs['id'] = auto_id
if not self.form.is_bound: if not self.form.is_bound:
data = self.field.initial data = self.form.initial.get(self.name, self.field.initial)
else: else:
data = self.data data = self.data
return widget.render(self.html_name, data, attrs=attrs) 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 ...@@ -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 The ``widget`` argument lets you specify a ``Widget`` class to use when
rendering this ``Field``. See _`Widgets` below for more information. 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 More coming soon
================ ================
......
...@@ -2215,6 +2215,61 @@ validation error rather than using the initial value for 'username'. ...@@ -2215,6 +2215,61 @@ validation error rather than using the initial value for 'username'.
>>> p.is_valid() >>> p.is_valid()
False 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 ######################################################### # Forms with prefixes #########################################################
Sometimes it's necessary to have multiple forms display on the same HTML page, Sometimes it's necessary to have multiple forms display on the same HTML page,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment