summaryrefslogtreecommitdiff
path: root/docs/modelforms.txt
diff options
context:
space:
mode:
authorJustin Bronn <jbronn@gmail.com>2007-12-15 01:38:43 +0000
committerJustin Bronn <jbronn@gmail.com>2007-12-15 01:38:43 +0000
commit34560a01daee3c42a7c5ec462f38a485cccf4df7 (patch)
treec332688943fb10b1503654815a06093c1d52e493 /docs/modelforms.txt
parent5799c2e048ff829300af88ae839de20e1763ee1d (diff)
gis: Merged revisions 6672,6686-6688,6690,6693,6707-6708,6726,6730,6753,6755-6762,6764,6776-6777,6779,6782-6919 via svnmerge from trunk; reverted oracle backend `base.py` due to ikelly's patch in r6905.
git-svn-id: http://code.djangoproject.com/svn/django/branches/gis@6920 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'docs/modelforms.txt')
-rw-r--r--docs/modelforms.txt313
1 files changed, 313 insertions, 0 deletions
diff --git a/docs/modelforms.txt b/docs/modelforms.txt
new file mode 100644
index 0000000000..372abf9811
--- /dev/null
+++ b/docs/modelforms.txt
@@ -0,0 +1,313 @@
+==========================
+Using newforms with models
+==========================
+
+``ModelForm``
+=============
+
+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 helper class that let you create a ``Form``
+class from a Django model.
+
+For example::
+
+ >>> from django.newforms import ModelForm
+
+ # Create the form class.
+ >>> class ArticleForm(ModelForm):
+ ... class Meta:
+ ... model = Article
+
+ # Creating a form to add an article.
+ >>> form = ArticleForm()
+
+ # Creating a form to change an existing article.
+ >>> article = Article.objects.get(pk=1)
+ >>> form = ArticleForm(instance=article)
+
+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 ``max_length``
+ ``CommaSeparatedIntegerField`` ``CharField``
+ ``DateField`` ``DateField``
+ ``DateTimeField`` ``DateTimeField``
+ ``DecimalField`` ``DecimalField``
+ ``EmailField`` ``EmailField``
+ ``FileField`` ``FileField``
+ ``FilePathField`` ``CharField``
+ ``FloatField`` ``FloatField``
+ ``ForeignKey`` ``ModelChoiceField`` (see below)
+ ``ImageField`` ``ImageField``
+ ``IntegerField`` ``IntegerField``
+ ``IPAddressField`` ``IPAddressField``
+ ``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``
+ =============================== ========================================
+
+
+.. note::
+ The ``FloatField`` form field and ``DecimalField`` model and form fields
+ are new in the development version.
+
+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``. The choices will normally include the blank choice which is
+ selected by default. If the field is required, this forces the user to
+ make a selection. The blank choice will not be included if the model
+ field has ``blank=False`` and an explicit ``default`` value (the
+ ``default`` value will be initially selected instead).
+
+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(max_length=100)
+ title = models.CharField(max_length=3, choices=TITLE_CHOICES)
+ birth_date = models.DateField(blank=True, null=True)
+
+ def __unicode__(self):
+ return self.name
+
+ class Book(models.Model):
+ name = models.CharField(max_length=100)
+ authors = models.ManyToManyField(Author)
+
+ class AuthorForm(ModelForm):
+ class Meta:
+ model = Author
+
+ class BookForm(ModelForm):
+ class Meta:
+ model = Book
+
+With these models, the ``ModelForm`` subclasses above would be roughly
+equivalent to this (the only difference being the ``save()`` method, which
+we'll discuss in a moment.)::
+
+ 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)
+
+ class BookForm(forms.Form):
+ name = forms.CharField(max_length=100)
+ authors = forms.ModelMultipleChoiceField(queryset=Author.objects.all())
+
+The ``save()`` method
+---------------------
+
+Every form produced by ``ModelForm`` also has a ``save()``
+method. This method creates and saves a database object from the data
+bound to the form. A subclass of ``ModelForm`` can accept an existing
+model instance as the keyword argument ``instance``; if this is
+supplied, ``save()`` will update that instance. If it's not supplied,
+``save()`` will create a new instance of the specified model::
+
+ # 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()
+
+ # Create a form to edit an existing Article.
+ >>> a = Article.objects.get(pk=1)
+ >>> f = ArticleForm(instance=a)
+
+Note that ``save()`` will raise a ``ValueError`` if the data in the form
+doesn't validate -- i.e., ``if form.errors``.
+
+This ``save()`` method accepts an optional ``commit`` keyword argument, which
+accepts either ``True`` or ``False``. If you call ``save()`` with
+``commit=False``, then it will return an object that hasn't yet been saved to
+the database. In this case, it's up to you to call ``save()`` on the resulting
+model instance. This is useful if you want to do custom processing on the
+object before saving it. ``commit`` is ``True`` by default.
+
+Another side effect of using ``commit=False`` is seen when your model has
+a many-to-many relation with another model. If your model has a many-to-many
+relation and you specify ``commit=False`` when you save a form, Django cannot
+immediately save the form data for the many-to-many relation. This is because
+it isn't possible to save many-to-many data for an instance until the instance
+exists in the database.
+
+To work around this problem, every time you save a form using ``commit=False``,
+Django adds a ``save_m2m()`` method to your ``ModelForm`` subclass. After
+you've manually saved the instance produced by the form, you can invoke
+``save_m2m()`` to save the many-to-many form data. For example::
+
+ # Create a form instance with POST data.
+ >>> f = AuthorForm(request.POST)
+
+ # Create, but don't save the new author instance.
+ >>> new_author = f.save(commit=False)
+
+ # Modify the author in some way.
+ >>> new_author.some_field = 'some_value'
+
+ # Save the new instance.
+ >>> new_author.save()
+
+ # Now, save the many-to-many data for the form.
+ >>> f.save_m2m()
+
+Calling ``save_m2m()`` is only required if you use ``save(commit=False)``.
+When you use a simple ``save()`` on a form, all data -- including
+many-to-many data -- is saved without the need for any additional method calls.
+For example::
+
+ # Create a form instance with POST data.
+ >>> a = Author()
+ >>> f = AuthorForm(a, request.POST)
+
+ # Create and save the new author instance. There's no need to do anything else.
+ >>> new_author = f.save()
+
+Using a subset of fields on the form
+------------------------------------
+
+In some cases, you may not want all the model fields to appear on the generated
+form. There are three ways of telling ``ModelForm`` 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 ``ModelForm`` will not include that
+ field.
+
+ 2. Use the ``fields`` attribute of the ``ModelForm``'s inner ``Meta`` class.
+ This attribute, if given, should be a list of field names to include in
+ the form.
+
+ 3. Use the ``exclude`` attribute of the ``ModelForm``'s inner ``Meta`` class.
+ This attribute, if given, should be a list of field names to exclude
+ 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`` or ``exclude`` like this::
+
+ class PartialAuthorForm(ModelForm):
+ class Meta:
+ model = Author
+ fields = ('name', 'title')
+
+ class PartialAuthorForm(ModelForm):
+ class Meta:
+ model = Author
+ exclude = ('birth_date',)
+
+ Since the Author model has only 3 fields, 'name', 'title', and
+ 'birth_date', the forms above will contain exactly the same fields.
+
+.. note::
+
+ If you specify ``fields`` or ``exclude`` when creating a form with
+ ``ModelForm``, then the fields that are not in the resulting form will not
+ be set by the form's ``save()`` method. Django will prevent any attempt to
+ save an incomplete model, so if the model does not allow the missing fields
+ to be empty, and does not provide a default value for the missing fields,
+ any attempt to ``save()`` a ``ModelForm`` with missing fields will fail.
+ To avoid this failure, you must instantiate your model with initial values
+ for the missing, but required fields, or use ``save(commit=False)`` and
+ manually set anyextra required fields::
+
+ instance = Instance(required_field='value')
+ form = InstanceForm(request.POST, instance=instance)
+ new_instance = form.save()
+
+ instance = form.save(commit=False)
+ instance.required_field = 'new value'
+ new_instance = instance.save()
+
+ See the `section on saving forms`_ for more details on using
+ ``save(commit=False)``.
+
+.. _section on saving forms: `The save() method`_
+
+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
+``ModelForm`` gives you the flexibility of changing the form field type
+for a given model field. You do this by declaratively specifying fields like
+you would in a regular ``Form``. Declared fields will override the default
+ones generated by using the ``model`` attribute.
+
+For example, if you wanted to use ``MyDateFormField`` for the ``pub_date``
+field, you could do the following::
+
+ >>> class ArticleForm(ModelForm):
+ ... pub_date = MyDateFormField()
+ ...
+ ... class Meta:
+ ... model = Article