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,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
=======