summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorMalcolm Tredinnick <malcolm.tredinnick@gmail.com>2007-12-02 19:29:54 +0000
committerMalcolm Tredinnick <malcolm.tredinnick@gmail.com>2007-12-02 19:29:54 +0000
commit51dc4ecf943d1dcc044ed956925760f9d480f56c (patch)
tree2eb4f5674cf0ae05e1d214366bac506938b6f6f2 /docs
parent61947f0635bdf5a4043caa2562e085058b2d19a8 (diff)
Fixed #6042 -- ModelForms implementation from Joseph Kocherhans. Still might
need a little tweaking as people start to use it, but this is mostly complete. git-svn-id: http://code.djangoproject.com/svn/django/trunk@6844 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'docs')
-rw-r--r--docs/form_for_model.txt418
-rw-r--r--docs/modelforms.txt310
-rw-r--r--docs/newforms.txt421
3 files changed, 734 insertions, 415 deletions
diff --git a/docs/form_for_model.txt b/docs/form_for_model.txt
new file mode 100644
index 0000000000..6761c15331
--- /dev/null
+++ b/docs/form_for_model.txt
@@ -0,0 +1,418 @@
+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 ``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)
+
+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``.
+
+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 the form created by ``form_for_model``.
+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.
+ >>> f = AuthorForm(request.POST)
+
+ # Create and save the new author instance. There's no need to do anything else.
+ >>> new_author = f.save()
+
+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()``,
+ then the fields that are *not* specified 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 ``form_for_model`` with missing fields will fail. To avoid
+ this failure, you must use ``save(commit=False)`` and manually set any
+ extra required fields::
+
+ instance = form.save(commit=False)
+ instance.required_field = 'new value'
+ 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
+``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(Article, 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.
+
+.. warning::
+ The field that is passed into the ``formfield_callback`` function in
+ ``form_for_model()`` and ``form_for_instance`` is the field instance from
+ your model's class. You **must not** alter that object at all; treat it
+ as read-only!
+
+ If you make any alterations to that object, it will affect any future
+ users of the model class, because you will have changed the field object
+ used to construct the class. This is almost certainly what you don't want
+ to have happen.
+
+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.
+
+Unlike ``form_for_model()``, a choice field in form created by
+``form_for_instance()`` will not include the blank choice if the respective
+model field has ``blank=False``. The initial choice is drawn from the instance.
+
+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()``.
+
+Let's modify the earlier `contact form`_ view example a little bit. Suppose we
+have a ``Message`` model that holds each contact submission. Something like::
+
+ class Message(models.Model):
+ subject = models.CharField(max_length=100)
+ message = models.TextField()
+ sender = models.EmailField()
+ cc_myself = models.BooleanField(required=False)
+
+You could use this model to create a form (using ``form_for_model()``). You
+could also use existing ``Message`` instances to create a form for editing
+messages. The `simple example view`_ can be changed slightly to accept the ``id`` value
+of an existing ``Message`` and present it for editing::
+
+ def contact_edit(request, msg_id):
+ # Create the form from the message id.
+ message = get_object_or_404(Message, id=msg_id)
+ ContactForm = form_for_instance(message)
+
+ if request.method == 'POST':
+ form = ContactForm(request.POST)
+ if form.is_valid():
+ form.save()
+ return HttpResponseRedirect('/url/on_success/')
+ else:
+ form = ContactForm()
+ return render_to_response('contact.html', {'form': form})
+
+Aside from how we create the ``ContactForm`` class here, the main point to
+note is that the form display in the ``GET`` branch of the function
+will use the values from the ``message`` instance as initial values for the
+form field.
+
+.. _contact form: ../newforms/#simple-view-example
+.. _`simple example view`: ../newforms/#simple-view-example
+
+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.
diff --git a/docs/modelforms.txt b/docs/modelforms.txt
new file mode 100644
index 0000000000..5e94128ba3
--- /dev/null
+++ b/docs/modelforms.txt
@@ -0,0 +1,310 @@
+==========================
+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.
+ >>> article\ = Article()
+ >>> form = ArticleForm(article)
+
+ # Creating a form to change an existing article.
+ >>> article = Article.objects.get(pk=1)
+ >>> form = ArticleForm(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`` also requires a model instance as the first
+arument to its constructor. For example::
+
+ # Create a form instance from POST data.
+ >>> a = Article()
+ >>> f = ArticleForm(a, 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``.
+
+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.
+ >>> a = Author()
+ >>> f = AuthorForm(a, 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(requiured_field='value')
+ form = InstanceForm(instance, request.POST)
+ 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
diff --git a/docs/newforms.txt b/docs/newforms.txt
index 6635063e3c..ac2cfb1f72 100644
--- a/docs/newforms.txt
+++ b/docs/newforms.txt
@@ -1770,423 +1770,14 @@ You can then use this field whenever you have a form that requires a comment::
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.
+The prefered way of generating forms that work with models is explained in the
+`ModelForms documentation`_.
-For this reason, Django provides a few helper functions that let you create a
-``Form`` class from a Django model.
+Looking for the ``form_for_model`` and ``form_for_instance`` documentation?
+They've been deprecated, but you can still `view the documentation`_.
-``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 ``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 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, in which
- case 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)
-
-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``.
-
-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 the form created by ``form_for_model``.
-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.
- >>> f = AuthorForm(request.POST)
-
- # Create and save the new author instance. There's no need to do anything else.
- >>> new_author = f.save()
-
-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()``,
- then the fields that are *not* specified 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 ``form_for_model`` with missing fields will fail. To avoid
- this failure, you must use ``save(commit=False)`` and manually set any
- extra required fields::
-
- instance = form.save(commit=False)
- instance.required_field = 'new value'
- 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
-``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(Article, 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.
-
-.. warning::
- The field that is passed into the ``formfield_callback`` function in
- ``form_for_model()`` and ``form_for_instance`` is the field instance from
- your model's class. You **must not** alter that object at all; treat it
- as read-only!
-
- If you make any alterations to that object, it will affect any future
- users of the model class, because you will have changed the field object
- used to construct the class. This is almost certainly what you don't want
- to have happen.
-
-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.
-
-Unlike ``form_for_model()``, a choice field in form created by
-``form_for_instance()`` will not include the blank choice if the respective
-model field has ``blank=False``. The initial choice is drawn from the instance.
-
-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()``.
-
-Let's modify the earlier `contact form`_ view example a little bit. Suppose we
-have a ``Message`` model that holds each contact submission. Something like::
-
- class Message(models.Model):
- subject = models.CharField(max_length=100)
- message = models.TextField()
- sender = models.EmailField()
- cc_myself = models.BooleanField(required=False)
-
-You could use this model to create a form (using ``form_for_model()``). You
-could also use existing ``Message`` instances to create a form for editing
-messages. The earlier_ view can be changed slightly to accept the ``id`` value
-of an existing ``Message`` and present it for editing::
-
- def contact_edit(request, msg_id):
- # Create the form from the message id.
- message = get_object_or_404(Message, id=msg_id)
- ContactForm = form_for_instance(message)
-
- if request.method == 'POST':
- form = ContactForm(request.POST)
- if form.is_valid():
- form.save()
- return HttpResponseRedirect('/url/on_success/')
- else:
- form = ContactForm()
- return render_to_response('contact.html', {'form': form})
-
-Aside from how we create the ``ContactForm`` class here, the main point to
-note is that the form display in the ``GET`` branch of the function
-will use the values from the ``message`` instance as initial values for the
-form field.
-
-.. _contact form: `Simple view example`_
-.. _earlier: `Simple view example`_
-
-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.
+.. _ModelForms documentation: ../modelforms/
+.. _view the documentation: ../form_for_model/
More coming soon
================