Edited changes to docs/newforms.txt from [5202]

git-svn-id: http://code.djangoproject.com/svn/django/trunk@5212 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Adrian Holovaty 2007-05-12 17:02:44 +00:00
parent c7d7b6da3c
commit 6500f3fefa
1 changed files with 238 additions and 95 deletions

View File

@ -873,158 +873,304 @@ mentioned above (``required``, ``label``, ``initial``, ``widget``,
Generating forms for models
===========================
Although you can build customized forms by specifying the fields manually,
in many cases you won't need to. Django provides helper methods to simplify the
common cases of form creation.
If you're building a database-driven app, chances are you'll have forms that
map closely to Django models. For instance, you might have a ``BlogComment``
model, and you want to create a form that lets people submit comments. In this
case, it would be redundant to define the field types in your form, because
you've already defined the fields in your model.
For this reason, Django provides a few helper functions that let you create a
``Form`` class from a Django model.
``form_for_model()``
--------------------
This method creates a form based upon the definition for a specific model.
``form_for_model()`` examines the model definition, and creates a new form
class that contains a form field for each model field that is defined.
The method ``django.newforms.form_for_model()`` creates a form based on the
definition of a specific model. Pass it the model class, and it will return a
``Form`` class that contains a form field for each model field.
The type of fields produced on the generated form is determined by the type
of the model fields. For example, a ``CharField`` on a model will be
represented with a ``CharField`` on the form. Each ``ManyToManyField``
on the model will be represented with a ``MultipleChoiceField`` on the
form. Each ``ForeignKey`` will be represented with a ``ChoiceField``.
A ``ChoiceField`` is also used for any model field that has a ``choices``
attribute specified.
For example::
``form_for_model()`` returns a generated class. This class must then be
instantiated::
>>> from django.newforms import form_for_model
# Create the form class
# Create the form class.
>>> ArticleForm = form_for_model(Article)
# Create an empty form instance
>>> f = ArticleForm()
The form produced by ``form_for_model`` also has a ``save()`` method. Once the
form contains valid data, the ``save()`` method can be used to create a model
instance with the attribute values described on the form::
# Create a form instance populated with POST data
# Create an empty form instance.
>>> f = ArticleForm()
It bears repeating that ``form_for_model()`` takes the model *class*, not a
model instance, and it returns a ``Form`` *class*, not a ``Form`` instance.
Field types
~~~~~~~~~~~
The generated ``Form`` class will have a form field for every model field. Each
model field has a corresponding default form field. For example, a
``CharField`` on a model is represented as a ``CharField`` on a form. A
model ``ManyToManyField`` is represented as a ``MultipleChoiceField``. Here is
the full list of conversions:
=============================== ========================================
Model field Form field
=============================== ========================================
``AutoField`` Not represented in the form
``BooleanField`` ``BooleanField``
``CharField`` ``CharField`` with ``max_length`` set to
the model field's ``maxlength``
``CommaSeparatedIntegerField`` ``CharField``
``DateField`` ``DateField``
``DateTimeField`` ``DateTimeField``
``EmailField`` ``EmailField``
``FileField`` ``CharField``
``FilePathField`` ``CharField``
``FloatField`` ``CharField``
``ForeignKey`` ``ModelChoiceField`` (see below)
``ImageField`` ``CharField``
``IntegerField`` ``IntegerField``
``IPAddressField`` ``CharField``
``ManyToManyField`` ``ModelMultipleChoiceField`` (see
below)
``NullBooleanField`` ``CharField``
``PhoneNumberField`` ``USPhoneNumberField``
(from ``django.contrib.localflavor.us``)
``PositiveIntegerField`` ``IntegerField``
``PositiveSmallIntegerField`` ``IntegerField``
``SlugField`` ``CharField``
``SmallIntegerField`` ``IntegerField``
``TextField`` ``CharField`` with ``widget=Textarea``
``TimeField`` ``TimeField``
``URLField`` ``URLField`` with ``verify_exists`` set
to the model field's ``verify_exists``
``USStateField`` ``CharField with ``widget=USStateSelect``
(``USStateSelect`` is from
``django.contrib.localflavor.us``)
``XMLField`` ``CharField`` with ``widget=Textarea``
=============================== ========================================
As you might expect, the ``ForeignKey`` and ``ManyToManyField`` model field
types are special cases:
* ``ForeignKey`` is represented by ``django.newforms.ModelChoiceField``,
which is a ``ChoiceField`` whose choices are a model ``QuerySet``.
* ``ManyToManyField`` is represented by
``django.newforms.ModelMultipleChoiceField``, which is a
``MultipleChoiceField`` whose choices are a model ``QuerySet``.
In addition, each generated form field has attributes set as follows:
* If the model field has ``blank=True``, then ``required`` is set to
``False`` on the form field. Otherwise, ``required=True``.
* The form field's ``label`` is set to the ``verbose_name`` of the model
field, with the first character capitalized.
* The form field's ``help_text`` is set to the ``help_text`` of the model
field.
* If the model field has ``choices`` set, then the form field's ``widget``
will be set to ``Select``, with choices coming from the model field's
``choices``.
Finally, note that you can override the form field used for a given model
field. See "Overriding the default field types" below.
A full example
~~~~~~~~~~~~~~
Consider this set of models::
from django.db import models
TITLE_CHOICES = (
('MR', 'Mr.'),
('MRS', 'Mrs.'),
('MS', 'Ms.'),
)
class Author(models.Model):
name = models.CharField(maxlength=100)
title = models.CharField(maxlength=3, choices=TITLE_CHOICES)
birth_date = models.DateField(blank=True, null=True)
def __str__(self):
return self.name
class Book(models.Model):
name = models.CharField(maxlength=100)
authors = models.ManyToManyField(Author)
With these models, a call to ``form_for_model(Author)`` would return a ``Form``
class equivalent to this::
class AuthorForm(forms.Form):
name = forms.CharField(max_length=100)
title = forms.CharField(max_length=3,
widget=forms.Select(choices=TITLE_CHOICES))
birth_date = forms.DateField(required=False)
A call to ``form_for_model(Book)`` would return a ``Form`` class equivalent to
this::
class BookForm(forms.Form):
name = forms.CharField(max_length=100)
authors = forms.ModelMultipleChoiceField(queryset=Author.objects.all())
The ``save()`` method
~~~~~~~~~~~~~~~~~~~~~
Every form produced by ``form_for_model()`` also has a ``save()`` method. This
method creates and saves a database object from the data bound to the form. For
example::
# Create a form instance from POST data.
>>> f = ArticleForm(request.POST)
# Save the new instance
# Save a new Article object from the form's data.
>>> new_article = f.save()
Note that ``save()`` will raise a ``ValueError`` if the data in the form
doesn't validate -- i.e., ``if form.errors``.
Using an alternate base class
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If you want to add other methods to the generated form, you can put those
methods onto a base class, and instruct ``form_for_model()`` to use that
base class.
If you want to add custom methods to the form generated by
``form_for_model()``, write a class that extends ``django.newforms.BaseForm``
and contains your custom methods. Then, use the ``form`` argument to
``form_for_model()`` to tell it to use your custom form as its base class.
For example::
By default, every form produced by ``form_for_model()`` extends
``django.newforms.forms.BaseForm``. However, if you provide a ``forms``
argument to ``form_for_model()``, Django will use that class as the base
for the form it generates::
# Create the new base class:
# Create the new base class.
>>> class MyBase(BaseForm):
... def fiddle(self):
... def my_method(self):
... # Do whatever the method does
# Create the form class with a different base class
# Create the form class with a different base class.
>>> ArticleForm = form_for_model(Article, form=MyBase)
# Instantiate the form
# Instantiate the form.
>>> f = ArticleForm()
# Use the base class method
>>> f.fiddle()
Putting a subset of fields on the form
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Use the base class method.
>>> f.my_method()
Using a subset of fields on the form
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
**New in Django development version**
In some cases, you may not want all the model fields to appear on the form.
One option is to set ``editable=False`` on the model field. ``form_for_model()``
will not include any non-editable fields on a generated form instance.
In some cases, you may not want all the model fields to appear on the generated
form. There are two ways of telling ``form_for_model()`` to use only a subset
of the model fields:
However, if you just want to exclude a field from one specific form, you
can use the ``fields`` argument. If you provide a fields argument to
``form_for_model()``, only the fields named will be included on the form.
For example, if you only want the 'title' and 'pub_date' attributes to be
included on the Article form, you would call::
1. Set ``editable=False`` on the model field. As a result, *any* form
created from the model via ``form_for_model()`` will not include that
field.
>>> PartialArticleForm = form_for_model(Article, fields=('title', 'pub_date'))
2. Use the ``fields`` argument to ``form_for_model()``. This argument, if
given, should be a list of field names to include in the form.
For example, if you want a form for the ``Author`` model (defined above)
that includes only the ``name`` and ``title`` fields, you would specify
``fields`` like this::
PartialArticleForm = form_for_model(Author, fields=('name', 'title'))
.. note::
If you specify ``fields`` when creating a form with ``form_for_model()``
make sure that the fields that are *not* specified can provide default
values, or are allowed to have a value of ``None``. If a field isn't
specified on a form, the object created from the form can't provide
a value for that attribute, which will prevent the new instance from
If you specify ``fields`` when creating a form with ``form_for_model()``,
make sure that the fields that are *not* specified can provide default
values, or are allowed to have a value of ``None``. If a field isn't
specified on a form, the object created from the form can't provide
a value for that attribute, which will prevent the new instance from
being saved.
Overriding the default field types
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Although the form field types generated by ``form_for_model()`` are suitable
for most general purposes, you may have need to override the default field
types on a specific form. In order to do this, ``form_for_model()`` provides
access to the *formfield callback*.
The default field types, as described in the "Field types" table above, are
sensible defaults; if you have a ``DateField`` in your model, chances are you'd
want that to be represented as a ``DateField`` in your form. But
``form_for_model()`` gives you the flexibility of changing the form field type
for a given model field. You do this by specifying a *formfield callback*.
The formfield callback is a function that, when provided with a model field,
A formfield callback is a function that, when provided with a model field,
returns a form field instance. When constructing a form, ``form_for_model()``
asks the formfield callback to provide form field types. The default
implementation asks the model field for an appropriate field type; however,
any other strategy may be employed. If you need to use an alternate strategy,
you can define your own callback, and provide it to ``form_for_model()`` using
the ``formfield_callback`` argument.
asks the formfield callback to provide form field types.
By default, ``form_for_model()`` calls the ``formfield()`` method on the model
field::
def default_callback(field, **kwargs):
return field.formfield(**kwargs)
The ``kwargs`` are any keyword arguments that might be passed to the form
field, such as ``required=True`` or ``label='Foo'``.
For example, if you wanted to use ``MyDateFormField`` for any ``DateField``
fields on the model, you could define the callback::
field on the model, you could define the callback::
>>> def my_fields(field, **kwargs):
>>> def my_callback(field, **kwargs):
... if isinstance(field, models.DateField):
... return MyDateFormField(**kwargs)
... else:
... else:
... return field.formfield(**kwargs)
>>> ArticleForm = form_for_model(formfield_callback=my_fields)
Note that your callback needs to handle *all* possible model field types, not
just the ones that you want to behave differently to the default.
>>> ArticleForm = form_for_model(formfield_callback=my_callback)
Note that your callback needs to handle *all* possible model field types, not
just the ones that you want to behave differently to the default. That's why
this example has an ``else`` clause that implements the default behavior.
Finding the model associated with a form
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The model class that was used to construct the form is available
using the ``_model`` property of the generated form.
using the ``_model`` property of the generated form::
>>> ArticleForm = form_for_model(Article)
>>> ArticleForm._model
<class 'myapp.models.Article'>
``form_for_instance()``
-----------------------
``form_for_instance()`` is very similar to ``form_for_model()``. However,
rather than using a model class to generate a form, it uses an instance of a
model::
``form_for_instance()`` is like ``form_for_model()``, but it takes a model
instance instead of a model class::
# Create an article
>>> art = Article(... some data ...)
>>> art.save()
# Create a form
>>> ArticleForm = form_for_instance(art)
# Instantiate the form
>>> f = ArticleForm()
# Create an Author.
>>> a = Author(name='Joe Smith', title='MR', birth_date=None)
>>> a.save()
# Create a form for this particular Author.
>>> AuthorForm = form_for_instance(a)
# Instantiate the form.
>>> f = AuthorForm()
When a form created by ``form_for_instance()`` is created, the initial
data values for the form fields are drawn from the instance. However,
this data is not bound to the form. You will need to bind data to the
data values for the form fields are drawn from the instance. However,
this data is not bound to the form. You will need to bind data to the
form before the form can be saved.
When you call ``save()`` on a form created by ``form_for_instance()``,
the database instance will be updated.
When you call ``save()`` on a form created by ``form_for_instance()``,
the database instance will be updated. As in ``form_for_model()``, ``save()``
will raise ``ValueError`` if the data doesn't validate.
``form_for_instance()`` has ``form``, ``fields`` and ``formfield_callback``
``form_for_instance()`` has ``form``, ``fields`` and ``formfield_callback``
arguments that behave the same way as they do for ``form_for_model()``.
When should you use ``form_for_model()`` and ``form_for_instance()``?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The ``form_for_model()`` and ``form_for_instance()`` functions are meant to be
shortcuts for the common case. If you want to create a form whose fields map to
more than one model, or a form that contains fields that *aren't* on a model,
you shouldn't use these shortcuts. Creating a ``Form`` class the "long" way
isn't that difficult, after all.
More coming soon
================
@ -1035,6 +1181,3 @@ what's possible.
If you're really itching to learn and use this library, please be patient.
We're working hard on finishing both the code and documentation.
Widgets
=======