mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	git-svn-id: http://code.djangoproject.com/svn/django/branches/queryset-refactor@6954 bcc190cf-cafb-0310-a4f2-bffc1f526a37
		
			
				
	
	
		
			426 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			426 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| Generating forms for models
 | |
| ===========================
 | |
| 
 | |
| .. admonition:: Note
 | |
| 
 | |
|     The APIs described in this document have been deprecated. If you're
 | |
|     developing new code, use `ModelForms`_ instead.
 | |
| 
 | |
| .. _ModelForms: ../modelforms/
 | |
| 
 | |
| 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.
 |