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:
parent
c7d7b6da3c
commit
6500f3fefa
|
@ -873,88 +873,214 @@ mentioned above (``required``, ``label``, ``initial``, ``widget``,
|
||||||
Generating forms for models
|
Generating forms for models
|
||||||
===========================
|
===========================
|
||||||
|
|
||||||
Although you can build customized forms by specifying the fields manually,
|
If you're building a database-driven app, chances are you'll have forms that
|
||||||
in many cases you won't need to. Django provides helper methods to simplify the
|
map closely to Django models. For instance, you might have a ``BlogComment``
|
||||||
common cases of form creation.
|
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()``
|
``form_for_model()``
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
This method creates a form based upon the definition for a specific model.
|
The method ``django.newforms.form_for_model()`` creates a form based on the
|
||||||
``form_for_model()`` examines the model definition, and creates a new form
|
definition of a specific model. Pass it the model class, and it will return a
|
||||||
class that contains a form field for each model field that is defined.
|
``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
|
For example::
|
||||||
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.
|
|
||||||
|
|
||||||
``form_for_model()`` returns a generated class. This class must then be
|
>>> from django.newforms import form_for_model
|
||||||
instantiated::
|
|
||||||
|
|
||||||
# Create the form class
|
# Create the form class.
|
||||||
>>> ArticleForm = form_for_model(Article)
|
>>> ArticleForm = form_for_model(Article)
|
||||||
|
|
||||||
# Create an empty form instance
|
# Create an empty form instance.
|
||||||
>>> f = ArticleForm()
|
>>> f = ArticleForm()
|
||||||
|
|
||||||
The form produced by ``form_for_model`` also has a ``save()`` method. Once the
|
It bears repeating that ``form_for_model()`` takes the model *class*, not a
|
||||||
form contains valid data, the ``save()`` method can be used to create a model
|
model instance, and it returns a ``Form`` *class*, not a ``Form`` instance.
|
||||||
instance with the attribute values described on the form::
|
|
||||||
|
|
||||||
# Create a form instance populated with POST data
|
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)
|
>>> f = ArticleForm(request.POST)
|
||||||
|
|
||||||
# Save the new instance
|
# Save a new Article object from the form's data.
|
||||||
>>> new_article = f.save()
|
>>> 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
|
Using an alternate base class
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
If you want to add other methods to the generated form, you can put those
|
If you want to add custom methods to the form generated by
|
||||||
methods onto a base class, and instruct ``form_for_model()`` to use that
|
``form_for_model()``, write a class that extends ``django.newforms.BaseForm``
|
||||||
base class.
|
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
|
# Create the new base class.
|
||||||
``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:
|
|
||||||
>>> class MyBase(BaseForm):
|
>>> class MyBase(BaseForm):
|
||||||
... def fiddle(self):
|
... def my_method(self):
|
||||||
... # Do whatever the method does
|
... # 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)
|
>>> ArticleForm = form_for_model(Article, form=MyBase)
|
||||||
|
|
||||||
# Instantiate the form
|
# Instantiate the form.
|
||||||
>>> f = ArticleForm()
|
>>> f = ArticleForm()
|
||||||
|
|
||||||
# Use the base class method
|
# Use the base class method.
|
||||||
>>> f.fiddle()
|
>>> f.my_method()
|
||||||
|
|
||||||
|
Using a subset of fields on the form
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
Putting a subset of fields on the form
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
**New in Django development version**
|
**New in Django development version**
|
||||||
|
|
||||||
In some cases, you may not want all the model fields to appear on the form.
|
In some cases, you may not want all the model fields to appear on the generated
|
||||||
One option is to set ``editable=False`` on the model field. ``form_for_model()``
|
form. There are two ways of telling ``form_for_model()`` to use only a subset
|
||||||
will not include any non-editable fields on a generated form instance.
|
of the model fields:
|
||||||
|
|
||||||
However, if you just want to exclude a field from one specific form, you
|
1. Set ``editable=False`` on the model field. As a result, *any* form
|
||||||
can use the ``fields`` argument. If you provide a fields argument to
|
created from the model via ``form_for_model()`` will not include that
|
||||||
``form_for_model()``, only the fields named will be included on the form.
|
field.
|
||||||
For example, if you only want the 'title' and 'pub_date' attributes to be
|
|
||||||
included on the Article form, you would call::
|
|
||||||
|
|
||||||
>>> 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::
|
.. note::
|
||||||
If you specify ``fields`` when creating a form with ``form_for_model()``
|
|
||||||
|
If you specify ``fields`` when creating a form with ``form_for_model()``,
|
||||||
make sure that the fields that are *not* specified can provide default
|
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
|
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
|
specified on a form, the object created from the form can't provide
|
||||||
|
@ -964,55 +1090,65 @@ included on the Article form, you would call::
|
||||||
Overriding the default field types
|
Overriding the default field types
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
Although the form field types generated by ``form_for_model()`` are suitable
|
The default field types, as described in the "Field types" table above, are
|
||||||
for most general purposes, you may have need to override the default field
|
sensible defaults; if you have a ``DateField`` in your model, chances are you'd
|
||||||
types on a specific form. In order to do this, ``form_for_model()`` provides
|
want that to be represented as a ``DateField`` in your form. But
|
||||||
access to the *formfield callback*.
|
``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()``
|
returns a form field instance. When constructing a form, ``form_for_model()``
|
||||||
asks the formfield callback to provide form field types. The default
|
asks the formfield callback to provide form field types.
|
||||||
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,
|
By default, ``form_for_model()`` calls the ``formfield()`` method on the model
|
||||||
you can define your own callback, and provide it to ``form_for_model()`` using
|
field::
|
||||||
the ``formfield_callback`` argument.
|
|
||||||
|
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``
|
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):
|
... if isinstance(field, models.DateField):
|
||||||
... return MyDateFormField(**kwargs)
|
... return MyDateFormField(**kwargs)
|
||||||
... else:
|
... else:
|
||||||
... return field.formfield(**kwargs)
|
... return field.formfield(**kwargs)
|
||||||
|
|
||||||
>>> ArticleForm = form_for_model(formfield_callback=my_fields)
|
>>> ArticleForm = form_for_model(formfield_callback=my_callback)
|
||||||
|
|
||||||
Note that your callback needs to handle *all* possible model field types, not
|
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.
|
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
|
Finding the model associated with a form
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
The model class that was used to construct the form is available
|
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()``
|
||||||
-----------------------
|
-----------------------
|
||||||
|
|
||||||
``form_for_instance()`` is very similar to ``form_for_model()``. However,
|
``form_for_instance()`` is like ``form_for_model()``, but it takes a model
|
||||||
rather than using a model class to generate a form, it uses an instance of a
|
instance instead of a model class::
|
||||||
model::
|
|
||||||
|
|
||||||
# Create an article
|
# Create an Author.
|
||||||
>>> art = Article(... some data ...)
|
>>> a = Author(name='Joe Smith', title='MR', birth_date=None)
|
||||||
>>> art.save()
|
>>> a.save()
|
||||||
|
|
||||||
# Create a form
|
# Create a form for this particular Author.
|
||||||
>>> ArticleForm = form_for_instance(art)
|
>>> AuthorForm = form_for_instance(a)
|
||||||
|
|
||||||
# Instantiate the form
|
# Instantiate the form.
|
||||||
>>> f = ArticleForm()
|
>>> f = AuthorForm()
|
||||||
|
|
||||||
When a form created by ``form_for_instance()`` is created, the initial
|
When a form created by ``form_for_instance()`` is created, the initial
|
||||||
data values for the form fields are drawn from the instance. However,
|
data values for the form fields are drawn from the instance. However,
|
||||||
|
@ -1020,11 +1156,21 @@ this data is not bound to the form. You will need to bind data to the
|
||||||
form before the form can be saved.
|
form before the form can be saved.
|
||||||
|
|
||||||
When you call ``save()`` on a form created by ``form_for_instance()``,
|
When you call ``save()`` on a form created by ``form_for_instance()``,
|
||||||
the database instance will be updated.
|
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()``.
|
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
|
More coming soon
|
||||||
================
|
================
|
||||||
|
|
||||||
|
@ -1035,6 +1181,3 @@ what's possible.
|
||||||
|
|
||||||
If you're really itching to learn and use this library, please be patient.
|
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.
|
We're working hard on finishing both the code and documentation.
|
||||||
|
|
||||||
Widgets
|
|
||||||
=======
|
|
||||||
|
|
Loading…
Reference in New Issue