summaryrefslogtreecommitdiff
path: root/docs/newforms.txt
diff options
context:
space:
mode:
Diffstat (limited to 'docs/newforms.txt')
-rw-r--r--docs/newforms.txt305
1 files changed, 302 insertions, 3 deletions
diff --git a/docs/newforms.txt b/docs/newforms.txt
index ddb850f54c..123b554bde 100644
--- a/docs/newforms.txt
+++ b/docs/newforms.txt
@@ -870,6 +870,308 @@ custom ``Field`` classes. To do this, just create a subclass of
mentioned above (``required``, ``label``, ``initial``, ``widget``,
``help_text``).
+Generating forms for models
+===========================
+
+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()``
+--------------------
+
+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.
+
+For example::
+
+ >>> from django.newforms import form_for_model
+
+ # Create the form class.
+ >>> ArticleForm = form_for_model(Article)
+
+ # 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 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 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::
+
+ # Create the new base class.
+ >>> class MyBase(BaseForm):
+ ... def my_method(self):
+ ... # Do whatever the method does
+
+ # Create the form class with a different base class.
+ >>> ArticleForm = form_for_model(Article, form=MyBase)
+
+ # Instantiate the form.
+ >>> f = ArticleForm()
+
+ # 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 generated
+form. There are two ways of telling ``form_for_model()`` to use only a subset
+of the model fields:
+
+ 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.
+
+ 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
+ being saved.
+
+Overriding the default field types
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+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**.
+
+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.
+
+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``
+field on the model, you could define the callback::
+
+ >>> def my_callback(field, **kwargs):
+ ... if isinstance(field, models.DateField):
+ ... return MyDateFormField(**kwargs)
+ ... else:
+ ... return field.formfield(**kwargs)
+
+ >>> 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::
+
+ >>> ArticleForm = form_for_model(Article)
+ >>> ArticleForm._model
+ <class 'myapp.models.Article'>
+
+``form_for_instance()``
+-----------------------
+
+``form_for_instance()`` is like ``form_for_model()``, but it takes a model
+instance instead of a model class::
+
+ # 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
+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. As in ``form_for_model()``, ``save()``
+will raise ``ValueError`` if the data doesn't validate.
+
+``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
================
@@ -880,6 +1182,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
-=======