Author: adrian
Date: 2007-05-12 12:02:44 -0500 (Sat, 12 May 2007)
New Revision: 5212

Modified:
   django/trunk/docs/newforms.txt
Log:
Edited changes to docs/newforms.txt from [5202]

Modified: django/trunk/docs/newforms.txt
===================================================================
--- django/trunk/docs/newforms.txt      2007-05-12 16:53:27 UTC (rev 5211)
+++ django/trunk/docs/newforms.txt      2007-05-12 17:02:44 UTC (rev 5212)
@@ -873,158 +873,304 @@
 Generating forms for models
 ===========================
 
-Although you can build customized forms by specifying the fields manually,
-in many cases you won't need to. Django provides helper methods to simplify the
-common cases of form creation.
+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()``
 --------------------
 
-This method creates a form based upon the definition for a specific model. 
-``form_for_model()`` examines the model definition, and creates a new form
-class that contains a form field for each model field that is defined.
+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.
 
-The type of fields produced on the generated form is determined by the type
-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.
+For example::
 
-``form_for_model()`` returns a generated class. This class must then be 
-instantiated::
+    >>> from django.newforms import form_for_model
 
-    # Create the form class
+    # Create the form class.
     >>> ArticleForm = form_for_model(Article)
-    
-    # Create an empty form instance
+
+    # Create an empty form instance.
     >>> f = ArticleForm()
- 
-The form produced by ``form_for_model`` also has a ``save()`` method. Once the
-form contains valid data, the ``save()`` method can be used to create a model
-instance with the attribute values described on the form::
 
-    # Create a form instance populated with POST data
+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 the new instance
+    # 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 other methods to the generated form, you can put those 
-methods onto a base class, and instruct ``form_for_model()`` to use that
-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::
 
-By default, every form produced by ``form_for_model()`` extends 
-``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:
+    # Create the new base class.
     >>> class MyBase(BaseForm):
-    ...     def fiddle(self):
+    ...     def my_method(self):
     ...         # 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)
 
-    # Instantiate the form
+    # Instantiate the form.
     >>> f = ArticleForm()
-    
-    # Use the base class method
-    >>> f.fiddle()
 
-Putting a subset of fields on the form
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+    # 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 form. 
-One option is to set ``editable=False`` on the model field. 
``form_for_model()``
-will not include any non-editable fields on a generated form instance.
+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:
 
-However, if you just want to exclude a field from one specific form, you
-can use the ``fields`` argument. If you provide a fields argument to
-``form_for_model()``, only the fields named will be included on the form. 
-For example, if you only want the 'title' and 'pub_date' attributes to be 
-included on the Article form, you would call::
+    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.
 
-    >>> 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::
-    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 
+
+    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
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-Although the form field types generated by ``form_for_model()`` are suitable
-for most general purposes, you may have need to override the default field
-types on a specific form. In order to do this, ``form_for_model()`` provides 
-access to the *formfield callback*.
+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*.
 
-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()``
-asks the formfield callback to provide form field types. The default 
-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, 
-you can define your own callback, and provide it to ``form_for_model()`` using 
-the ``formfield_callback`` argument. 
+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``
-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):
     ...         return MyDateFormField(**kwargs)
-    ...     else:     
+    ...     else:
     ...         return field.formfield(**kwargs)
-    
-    >>> ArticleForm = form_for_model(formfield_callback=my_fields)
 
-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.
+    >>> 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.
-     
+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 very similar to ``form_for_model()``. However,
-rather than using a model class to generate a form, it uses an instance of a 
-model::
+``form_for_instance()`` is like ``form_for_model()``, but it takes a model
+instance instead of a model class::
 
-    # Create an article
-    >>> art = Article(... some data ...)
-    >>> art.save()
-    
-    # Create a form
-    >>> ArticleForm = form_for_instance(art)
-    
-    # Instantiate the form
-    >>> f = ArticleForm()
+    # 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 
+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.
+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`` 
+``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
 ================
 
@@ -1035,6 +1181,3 @@
 
 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
-=======


--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/django-updates?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to