Ticket #6042: modelforms.diff

File modelforms.diff, 81.2 KB (added by jkocherhans, 16 years ago)

Now with updated docs and less stupidity thanks to Malcolm.

  • django/newforms/models.py

    diff --git a/django/newforms/models.py b/django/newforms/models.py
    index 51ed16f..77b2b32 100644
    a b and database field objects.  
    66from django.utils.translation import ugettext_lazy as _
    77from django.utils.encoding import smart_unicode
    88from django.utils.datastructures import SortedDict
     9from django.core.exceptions import ImproperlyConfigured
    910
    10 from util import ValidationError
     11from util import ValidationError, ErrorList
    1112from forms import BaseForm
    1213from fields import Field, ChoiceField, EMPTY_VALUES
    1314from widgets import Select, SelectMultiple, MultipleHiddenInput
    1415
    1516__all__ = (
     17    'ModelForm', 'BaseModelForm', 'model_to_dict', 'fields_for_model',
    1618    'save_instance', 'form_for_model', 'form_for_instance', 'form_for_fields',
    1719    'ModelChoiceField', 'ModelMultipleChoiceField'
    1820)
    def form_for_fields(field_list):  
    132134                         for f in field_list if f.editable])
    133135    return type('FormForFields', (BaseForm,), {'base_fields': fields})
    134136
     137
     138# ModelForms #################################################################
     139
     140def model_to_dict(instance, fields=None, exclude=None):
     141    """
     142    Returns a dict containing the data in ``instance`` suitable for passing as
     143    a Form's ``initial`` keyword argument.
     144   
     145    ``fields`` is an optional list of field names. If provided, only the named
     146    fields will be included in the returned dict.
     147   
     148    ``exclude`` is an optional list of field names. If provided, the named
     149    fields will be excluded from the returned dict, even if they are listed in
     150    the ``fields`` argument.
     151    """
     152    # avoid a circular import
     153    from django.db.models.fields.related import ManyToManyField
     154    opts = instance._meta
     155    data = {}
     156    for f in opts.fields + opts.many_to_many:
     157        if not f.editable:
     158            continue
     159        if fields and not f.name in fields:
     160            continue
     161        if exclude and f.name in exclude:
     162            continue
     163        if isinstance(f, ManyToManyField):
     164            # If the object doesn't have a primry key yet, just use an empty
     165            # list for its m2m fields. Calling f.value_from_object will raise
     166            # an exception.
     167            if instance.pk is None:
     168                data[f.name] = []
     169            else:
     170                # MultipleChoiceWidget needs a list of pks, not object instances.
     171                data[f.name] = [obj.pk for obj in f.value_from_object(instance)]
     172        else:
     173            data[f.name] = f.value_from_object(instance)
     174    return data
     175
     176def fields_for_model(model, fields=None, exclude=None, formfield_callback=lambda f: f.formfield()):
     177    """
     178    Returns a ``SortedDict`` containing form fields for the given model.
     179
     180    ``fields`` is an optional list of field names. If provided, only the named
     181    fields will be included in the returned fields.
     182   
     183    ``exclude`` is an optional list of field names. If provided, the named
     184    fields will be excluded from the returned fields, even if they are listed
     185    in the ``fields`` argument.
     186    """
     187    # TODO: if fields is provided, it would be nice to return fields in that order
     188    field_list = []
     189    opts = model._meta
     190    for f in opts.fields + opts.many_to_many:
     191        if not f.editable:
     192            continue
     193        if fields and not f.name in fields:
     194            continue
     195        if exclude and f.name in exclude:
     196            continue
     197        formfield = formfield_callback(f)
     198        if formfield:
     199            field_list.append((f.name, formfield))
     200    return SortedDict(field_list)
     201
     202class ModelFormOptions(object):
     203    def __init__(self, options=None):
     204        self.model = getattr(options, 'model', None)
     205        self.fields = getattr(options, 'fields', None)
     206        self.exclude = getattr(options, 'exclude', None)
     207
     208class ModelFormMetaclass(type):
     209    def __new__(cls, name, bases, attrs):
     210        # TODO: no way to specify formfield_callback yet, do we need one, or
     211        # should it be a special case for the admin?
     212        fields = [(field_name, attrs.pop(field_name)) for field_name, obj in attrs.items() if isinstance(obj, Field)]
     213        fields.sort(lambda x, y: cmp(x[1].creation_counter, y[1].creation_counter))
     214
     215        # If this class is subclassing another Form, add that Form's fields.
     216        # Note that we loop over the bases in *reverse*. This is necessary in
     217        # order to preserve the correct order of fields.
     218        for base in bases[::-1]:
     219            if hasattr(base, 'base_fields'):
     220                fields = base.base_fields.items() + fields
     221        declared_fields = SortedDict(fields)
     222
     223        opts = ModelFormOptions(attrs.get('Meta', None))
     224        attrs['_meta'] = opts
     225
     226        # Don't allow more than one Meta model defenition in bases. The fields
     227        # would be generated correctly, but the save method won't deal with
     228        # more than one object.
     229        base_models = []
     230        for base in bases:
     231            base_opts = getattr(base, '_meta', None)
     232            base_model = getattr(base_opts, 'model', None)
     233            if base_model is not None:
     234                base_models.append(base_model)
     235        if len(base_models) > 1:
     236            raise ImproperlyConfigured("%s's base classes define more than one model." % name)
     237
     238        # If a model is defined, extract form fields from it and add them to base_fields
     239        if attrs['_meta'].model is not None:
     240            # Don't allow a subclass to define a Meta model if a parent class has.
     241            # Technically the right fields would be generated, but the save
     242            # method will not deal with more than one model.
     243            for base in bases:
     244                base_opts = getattr(base, '_meta', None)
     245                base_model = getattr(base_opts, 'model', None)
     246                if base_model is not None:
     247                    raise ImproperlyConfigured('%s defines more than one model.' % name)
     248            model_fields = fields_for_model(opts.model, opts.fields, opts.exclude)
     249            # fields declared in base classes override fields from the model
     250            model_fields.update(declared_fields)
     251            attrs['base_fields'] = model_fields
     252        else:
     253            attrs['base_fields'] = declared_fields
     254        return type.__new__(cls, name, bases, attrs)
     255
     256class BaseModelForm(BaseForm):
     257    def __init__(self, instance, data=None, files=None, auto_id='id_%s', prefix=None,
     258                 initial=None, error_class=ErrorList, label_suffix=':'):
     259        self.instance = instance
     260        opts = self._meta
     261        object_data = model_to_dict(instance, opts.fields, opts.exclude)
     262        # if initial was provided, it should override the values from instance
     263        if initial is not None:
     264            object_data.update(initial)
     265        BaseForm.__init__(self, data, files, auto_id, prefix, object_data, error_class, label_suffix)
     266
     267    def save(self, commit=True):
     268        """
     269        Saves this ``form``'s cleaned_data into model instance ``self.instance``.
     270
     271        If commit=True, then the changes to ``instance`` will be saved to the
     272        database. Returns ``instance``.
     273        """
     274        if self.instance.pk is None:
     275            fail_message = 'created'
     276        else:
     277            fail_message = 'changed'
     278        return save_instance(self, self.instance, self._meta.fields, fail_message, commit)
     279
     280class ModelForm(BaseModelForm):
     281    __metaclass__ = ModelFormMetaclass
     282
     283
     284# Fields #####################################################################
     285
    135286class QuerySetIterator(object):
    136287    def __init__(self, queryset, empty_label, cache_choices):
    137288        self.queryset = queryset
    class QuerySetIterator(object):  
    142293        if self.empty_label is not None:
    143294            yield (u"", self.empty_label)
    144295        for obj in self.queryset:
    145             yield (obj._get_pk_val(), smart_unicode(obj))
     296            yield (obj.pk, smart_unicode(obj))
    146297        # Clear the QuerySet cache if required.
    147298        if not self.cache_choices:
    148299            self.queryset._result_cache = None
  • new file docs/form_for_model.txt

    diff --git a/docs/form_for_model.txt b/docs/form_for_model.txt
    new file mode 100644
    index 0000000..6761c15
    - +  
     1Generating forms for models
     2===========================
     3
     4If you're building a database-driven app, chances are you'll have forms that
     5map closely to Django models. For instance, you might have a ``BlogComment``
     6model, and you want to create a form that lets people submit comments. In this
     7case, it would be redundant to define the field types in your form, because
     8you've already defined the fields in your model.
     9
     10For this reason, Django provides a few helper functions that let you create a
     11``Form`` class from a Django model.
     12
     13``form_for_model()``
     14--------------------
     15
     16The method ``django.newforms.form_for_model()`` creates a form based on the
     17definition of a specific model. Pass it the model class, and it will return a
     18``Form`` class that contains a form field for each model field.
     19
     20For example::
     21
     22    >>> from django.newforms import form_for_model
     23
     24    # Create the form class.
     25    >>> ArticleForm = form_for_model(Article)
     26
     27    # Create an empty form instance.
     28    >>> f = ArticleForm()
     29
     30It bears repeating that ``form_for_model()`` takes the model *class*, not a
     31model instance, and it returns a ``Form`` *class*, not a ``Form`` instance.
     32
     33Field types
     34~~~~~~~~~~~
     35
     36The generated ``Form`` class will have a form field for every model field. Each
     37model field has a corresponding default form field. For example, a
     38``CharField`` on a model is represented as a ``CharField`` on a form. A
     39model ``ManyToManyField`` is represented as a ``MultipleChoiceField``. Here is
     40the full list of conversions:
     41
     42    ===============================  ========================================
     43    Model field                      Form field
     44    ===============================  ========================================
     45    ``AutoField``                    Not represented in the form
     46    ``BooleanField``                 ``BooleanField``
     47    ``CharField``                    ``CharField`` with ``max_length`` set to
     48                                     the model field's ``max_length``
     49    ``CommaSeparatedIntegerField``   ``CharField``
     50    ``DateField``                    ``DateField``
     51    ``DateTimeField``                ``DateTimeField``
     52    ``DecimalField``                 ``DecimalField``
     53    ``EmailField``                   ``EmailField``
     54    ``FileField``                    ``FileField``
     55    ``FilePathField``                ``CharField``
     56    ``FloatField``                   ``FloatField``
     57    ``ForeignKey``                   ``ModelChoiceField`` (see below)
     58    ``ImageField``                   ``ImageField``
     59    ``IntegerField``                 ``IntegerField``
     60    ``IPAddressField``               ``IPAddressField``
     61    ``ManyToManyField``              ``ModelMultipleChoiceField`` (see
     62                                     below)
     63    ``NullBooleanField``             ``CharField``
     64    ``PhoneNumberField``             ``USPhoneNumberField``
     65                                     (from ``django.contrib.localflavor.us``)
     66    ``PositiveIntegerField``         ``IntegerField``
     67    ``PositiveSmallIntegerField``    ``IntegerField``
     68    ``SlugField``                    ``CharField``
     69    ``SmallIntegerField``            ``IntegerField``
     70    ``TextField``                    ``CharField`` with ``widget=Textarea``
     71    ``TimeField``                    ``TimeField``
     72    ``URLField``                     ``URLField`` with ``verify_exists`` set
     73                                     to the model field's ``verify_exists``
     74    ``USStateField``                 ``CharField`` with
     75                                     ``widget=USStateSelect``
     76                                     (``USStateSelect`` is from
     77                                     ``django.contrib.localflavor.us``)
     78    ``XMLField``                     ``CharField`` with ``widget=Textarea``
     79    ===============================  ========================================
     80
     81
     82.. note::
     83    The ``FloatField`` form field and ``DecimalField`` model and form fields
     84    are new in the development version.
     85
     86As you might expect, the ``ForeignKey`` and ``ManyToManyField`` model field
     87types are special cases:
     88
     89    * ``ForeignKey`` is represented by ``django.newforms.ModelChoiceField``,
     90      which is a ``ChoiceField`` whose choices are a model ``QuerySet``.
     91
     92    * ``ManyToManyField`` is represented by
     93      ``django.newforms.ModelMultipleChoiceField``, which is a
     94      ``MultipleChoiceField`` whose choices are a model ``QuerySet``.
     95
     96In addition, each generated form field has attributes set as follows:
     97
     98    * If the model field has ``blank=True``, then ``required`` is set to
     99      ``False`` on the form field. Otherwise, ``required=True``.
     100
     101    * The form field's ``label`` is set to the ``verbose_name`` of the model
     102      field, with the first character capitalized.
     103
     104    * The form field's ``help_text`` is set to the ``help_text`` of the model
     105      field.
     106
     107    * If the model field has ``choices`` set, then the form field's ``widget``
     108      will be set to ``Select``, with choices coming from the model field's
     109      ``choices``. The choices will normally include the blank choice which is
     110      selected by default. If the field is required, this forces the user to
     111      make a selection. The blank choice will not be included if the model
     112      field has ``blank=False`` and an explicit ``default`` value (the
     113      ``default`` value will be initially selected instead).
     114
     115Finally, note that you can override the form field used for a given model
     116field. See "Overriding the default field types" below.
     117
     118A full example
     119~~~~~~~~~~~~~~
     120
     121Consider this set of models::
     122
     123    from django.db import models
     124
     125    TITLE_CHOICES = (
     126        ('MR', 'Mr.'),
     127        ('MRS', 'Mrs.'),
     128        ('MS', 'Ms.'),
     129    )
     130
     131    class Author(models.Model):
     132        name = models.CharField(max_length=100)
     133        title = models.CharField(max_length=3, choices=TITLE_CHOICES)
     134        birth_date = models.DateField(blank=True, null=True)
     135
     136        def __unicode__(self):
     137            return self.name
     138
     139    class Book(models.Model):
     140        name = models.CharField(max_length=100)
     141        authors = models.ManyToManyField(Author)
     142
     143With these models, a call to ``form_for_model(Author)`` would return a ``Form``
     144class equivalent to this::
     145
     146    class AuthorForm(forms.Form):
     147        name = forms.CharField(max_length=100)
     148        title = forms.CharField(max_length=3,
     149                    widget=forms.Select(choices=TITLE_CHOICES))
     150        birth_date = forms.DateField(required=False)
     151
     152A call to ``form_for_model(Book)`` would return a ``Form`` class equivalent to
     153this::
     154
     155    class BookForm(forms.Form):
     156        name = forms.CharField(max_length=100)
     157        authors = forms.ModelMultipleChoiceField(queryset=Author.objects.all())
     158
     159The ``save()`` method
     160~~~~~~~~~~~~~~~~~~~~~
     161
     162Every form produced by ``form_for_model()`` also has a ``save()`` method. This
     163method creates and saves a database object from the data bound to the form. For
     164example::
     165
     166    # Create a form instance from POST data.
     167    >>> f = ArticleForm(request.POST)
     168
     169    # Save a new Article object from the form's data.
     170    >>> new_article = f.save()
     171
     172Note that ``save()`` will raise a ``ValueError`` if the data in the form
     173doesn't validate -- i.e., ``if form.errors``.
     174
     175This ``save()`` method accepts an optional ``commit`` keyword argument, which
     176accepts either ``True`` or ``False``. If you call ``save()`` with
     177``commit=False``, then it will return an object that hasn't yet been saved to
     178the database. In this case, it's up to you to call ``save()`` on the resulting
     179model instance. This is useful if you want to do custom processing on the
     180object before saving it. ``commit`` is ``True`` by default.
     181
     182Another side effect of using ``commit=False`` is seen when your model has
     183a many-to-many relation with another model. If your model has a many-to-many
     184relation and you specify ``commit=False`` when you save a form, Django cannot
     185immediately save the form data for the many-to-many relation. This is because
     186it isn't possible to save many-to-many data for an instance until the instance
     187exists in the database.
     188
     189To work around this problem, every time you save a form using ``commit=False``,
     190Django adds a ``save_m2m()`` method to the form created by ``form_for_model``.
     191After you've manually saved the instance produced by the form, you can invoke
     192``save_m2m()`` to save the many-to-many form data. For example::
     193
     194    # Create a form instance with POST data.
     195    >>> f = AuthorForm(request.POST)
     196
     197    # Create, but don't save the new author instance.
     198    >>> new_author = f.save(commit=False)
     199
     200    # Modify the author in some way.
     201    >>> new_author.some_field = 'some_value'
     202
     203    # Save the new instance.
     204    >>> new_author.save()
     205
     206    # Now, save the many-to-many data for the form.
     207    >>> f.save_m2m()
     208
     209Calling ``save_m2m()`` is only required if you use ``save(commit=False)``.
     210When you use a simple ``save()`` on a form, all data -- including
     211many-to-many data -- is saved without the need for any additional method calls.
     212For example::
     213
     214    # Create a form instance with POST data.
     215    >>> f = AuthorForm(request.POST)
     216
     217    # Create and save the new author instance. There's no need to do anything else.
     218    >>> new_author = f.save()
     219
     220Using an alternate base class
     221~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     222
     223If you want to add custom methods to the form generated by
     224``form_for_model()``, write a class that extends ``django.newforms.BaseForm``
     225and contains your custom methods. Then, use the ``form`` argument to
     226``form_for_model()`` to tell it to use your custom form as its base class.
     227For example::
     228
     229    # Create the new base class.
     230    >>> class MyBase(BaseForm):
     231    ...     def my_method(self):
     232    ...         # Do whatever the method does
     233
     234    # Create the form class with a different base class.
     235    >>> ArticleForm = form_for_model(Article, form=MyBase)
     236
     237    # Instantiate the form.
     238    >>> f = ArticleForm()
     239
     240    # Use the base class method.
     241    >>> f.my_method()
     242
     243Using a subset of fields on the form
     244~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     245
     246**New in Django development version**
     247
     248In some cases, you may not want all the model fields to appear on the generated
     249form. There are two ways of telling ``form_for_model()`` to use only a subset
     250of the model fields:
     251
     252    1. Set ``editable=False`` on the model field. As a result, *any* form
     253       created from the model via ``form_for_model()`` will not include that
     254       field.
     255
     256    2. Use the ``fields`` argument to ``form_for_model()``. This argument, if
     257       given, should be a list of field names to include in the form.
     258
     259       For example, if you want a form for the ``Author`` model (defined above)
     260       that includes only the ``name`` and ``title`` fields, you would specify
     261       ``fields`` like this::
     262
     263           PartialArticleForm = form_for_model(Author, fields=('name', 'title'))
     264
     265.. note::
     266
     267    If you specify ``fields`` when creating a form with ``form_for_model()``,
     268    then the fields that are *not* specified will not be set by the form's
     269    ``save()`` method. Django will prevent any attempt to save an incomplete
     270    model, so if the model does not allow the missing fields to be empty, and
     271    does not provide a default value for the missing fields, any attempt to
     272    ``save()`` a ``form_for_model`` with missing fields will fail. To avoid
     273    this failure, you must use ``save(commit=False)`` and manually set any
     274    extra required fields::
     275
     276        instance = form.save(commit=False)
     277        instance.required_field = 'new value'
     278        instance.save()
     279
     280    See the `section on saving forms`_ for more details on using
     281    ``save(commit=False)``.
     282
     283.. _section on saving forms: `The save() method`_
     284
     285Overriding the default field types
     286~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     287
     288The default field types, as described in the "Field types" table above, are
     289sensible defaults; if you have a ``DateField`` in your model, chances are you'd
     290want that to be represented as a ``DateField`` in your form. But
     291``form_for_model()`` gives you the flexibility of changing the form field type
     292for a given model field. You do this by specifying a **formfield callback**.
     293
     294A formfield callback is a function that, when provided with a model field,
     295returns a form field instance. When constructing a form, ``form_for_model()``
     296asks the formfield callback to provide form field types.
     297
     298By default, ``form_for_model()`` calls the ``formfield()`` method on the model
     299field::
     300
     301    def default_callback(field, **kwargs):
     302        return field.formfield(**kwargs)
     303
     304The ``kwargs`` are any keyword arguments that might be passed to the form
     305field, such as ``required=True`` or ``label='Foo'``.
     306
     307For example, if you wanted to use ``MyDateFormField`` for any ``DateField``
     308field on the model, you could define the callback::
     309
     310    >>> def my_callback(field, **kwargs):
     311    ...     if isinstance(field, models.DateField):
     312    ...         return MyDateFormField(**kwargs)
     313    ...     else:
     314    ...         return field.formfield(**kwargs)
     315
     316    >>> ArticleForm = form_for_model(Article, formfield_callback=my_callback)
     317
     318Note that your callback needs to handle *all* possible model field types, not
     319just the ones that you want to behave differently to the default. That's why
     320this example has an ``else`` clause that implements the default behavior.
     321
     322.. warning::
     323    The field that is passed into the ``formfield_callback`` function in
     324    ``form_for_model()`` and ``form_for_instance`` is the field instance from
     325    your model's class. You **must not** alter that object at all; treat it
     326    as read-only!
     327
     328    If you make any alterations to that object, it will affect any future
     329    users of the model class, because you will have changed the field object
     330    used to construct the class. This is almost certainly what you don't want
     331    to have happen.
     332
     333Finding the model associated with a form
     334~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     335
     336The model class that was used to construct the form is available
     337using the ``_model`` property of the generated form::
     338
     339    >>> ArticleForm = form_for_model(Article)
     340    >>> ArticleForm._model
     341    <class 'myapp.models.Article'>
     342
     343``form_for_instance()``
     344-----------------------
     345
     346``form_for_instance()`` is like ``form_for_model()``, but it takes a model
     347instance instead of a model class::
     348
     349    # Create an Author.
     350    >>> a = Author(name='Joe Smith', title='MR', birth_date=None)
     351    >>> a.save()
     352
     353    # Create a form for this particular Author.
     354    >>> AuthorForm = form_for_instance(a)
     355
     356    # Instantiate the form.
     357    >>> f = AuthorForm()
     358
     359When a form created by ``form_for_instance()`` is created, the initial data
     360values for the form fields are drawn from the instance. However, this data is
     361not bound to the form. You will need to bind data to the form before the form
     362can be saved.
     363
     364Unlike ``form_for_model()``, a choice field in form created by
     365``form_for_instance()`` will not include the blank choice if the respective
     366model field has ``blank=False``. The initial choice is drawn from the instance.
     367
     368When you call ``save()`` on a form created by ``form_for_instance()``,
     369the database instance will be updated. As in ``form_for_model()``, ``save()``
     370will raise ``ValueError`` if the data doesn't validate.
     371
     372``form_for_instance()`` has ``form``, ``fields`` and ``formfield_callback``
     373arguments that behave the same way as they do for ``form_for_model()``.
     374
     375Let's modify the earlier `contact form`_ view example a little bit. Suppose we
     376have a ``Message`` model that holds each contact submission. Something like::
     377
     378    class Message(models.Model):
     379        subject = models.CharField(max_length=100)
     380        message = models.TextField()
     381        sender = models.EmailField()
     382        cc_myself = models.BooleanField(required=False)
     383
     384You could use this model to create a form (using ``form_for_model()``). You
     385could also use existing ``Message`` instances to create a form for editing
     386messages. The `simple example view`_ can be changed slightly to accept the ``id`` value
     387of an existing ``Message`` and present it for editing::
     388
     389    def contact_edit(request, msg_id):
     390        # Create the form from the message id.
     391        message = get_object_or_404(Message, id=msg_id)
     392        ContactForm = form_for_instance(message)
     393
     394        if request.method == 'POST':
     395            form = ContactForm(request.POST)
     396            if form.is_valid():
     397                form.save()
     398                return HttpResponseRedirect('/url/on_success/')
     399        else:
     400            form = ContactForm()
     401        return render_to_response('contact.html', {'form': form})
     402
     403Aside from how we create the ``ContactForm`` class here, the main point to
     404note is that the form display in the ``GET`` branch of the function
     405will use the values from the ``message`` instance as initial values for the
     406form field.
     407
     408.. _contact form: ../newforms/#simple-view-example
     409.. _`simple example view`: ../newforms/#simple-view-example
     410
     411When should you use ``form_for_model()`` and ``form_for_instance()``?
     412~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     413
     414The ``form_for_model()`` and ``form_for_instance()`` functions are meant to be
     415shortcuts for the common case. If you want to create a form whose fields map to
     416more than one model, or a form that contains fields that *aren't* on a model,
     417you shouldn't use these shortcuts. Creating a ``Form`` class the "long" way
     418isn't that difficult, after all.
  • new file docs/modelforms.txt

    diff --git a/docs/modelforms.txt b/docs/modelforms.txt
    new file mode 100644
    index 0000000..5e94128
    - +  
     1==========================
     2Using newforms with models
     3==========================
     4
     5``ModelForm``
     6=============
     7
     8If you're building a database-driven app, chances are you'll have forms that
     9map closely to Django models. For instance, you might have a ``BlogComment``
     10model, and you want to create a form that lets people submit comments. In this
     11case, it would be redundant to define the field types in your form, because
     12you've already defined the fields in your model.
     13
     14For this reason, Django provides a helper class that let you create a ``Form``
     15class from a Django model.
     16
     17For example::
     18
     19    >>> from django.newforms import ModelForm
     20   
     21    # Create the form class.
     22    >>> class ArticleForm(ModelForm):
     23    ...     class Meta:
     24    ...         model = Article
     25
     26    # Creating a form to add an article.
     27    >>> article\ = Article()
     28    >>> form = ArticleForm(article)
     29
     30    # Creating a form to change an existing article.
     31    >>> article = Article.objects.get(pk=1)
     32    >>> form = ArticleForm(article)
     33
     34Field types
     35-----------
     36
     37The generated ``Form`` class will have a form field for every model field. Each
     38model field has a corresponding default form field. For example, a
     39``CharField`` on a model is represented as a ``CharField`` on a form. A
     40model ``ManyToManyField`` is represented as a ``MultipleChoiceField``. Here is
     41the full list of conversions:
     42
     43    ===============================  ========================================
     44    Model field                      Form field
     45    ===============================  ========================================
     46    ``AutoField``                    Not represented in the form
     47    ``BooleanField``                 ``BooleanField``
     48    ``CharField``                    ``CharField`` with ``max_length`` set to
     49                                     the model field's ``max_length``
     50    ``CommaSeparatedIntegerField``   ``CharField``
     51    ``DateField``                    ``DateField``
     52    ``DateTimeField``                ``DateTimeField``
     53    ``DecimalField``                 ``DecimalField``
     54    ``EmailField``                   ``EmailField``
     55    ``FileField``                    ``FileField``
     56    ``FilePathField``                ``CharField``
     57    ``FloatField``                   ``FloatField``
     58    ``ForeignKey``                   ``ModelChoiceField`` (see below)
     59    ``ImageField``                   ``ImageField``
     60    ``IntegerField``                 ``IntegerField``
     61    ``IPAddressField``               ``IPAddressField``
     62    ``ManyToManyField``              ``ModelMultipleChoiceField`` (see
     63                                     below)
     64    ``NullBooleanField``             ``CharField``
     65    ``PhoneNumberField``             ``USPhoneNumberField``
     66                                     (from ``django.contrib.localflavor.us``)
     67    ``PositiveIntegerField``         ``IntegerField``
     68    ``PositiveSmallIntegerField``    ``IntegerField``
     69    ``SlugField``                    ``CharField``
     70    ``SmallIntegerField``            ``IntegerField``
     71    ``TextField``                    ``CharField`` with ``widget=Textarea``
     72    ``TimeField``                    ``TimeField``
     73    ``URLField``                     ``URLField`` with ``verify_exists`` set
     74                                     to the model field's ``verify_exists``
     75    ``USStateField``                 ``CharField`` with
     76                                     ``widget=USStateSelect``
     77                                     (``USStateSelect`` is from
     78                                     ``django.contrib.localflavor.us``)
     79    ``XMLField``                     ``CharField`` with ``widget=Textarea``
     80    ===============================  ========================================
     81
     82
     83.. note::
     84    The ``FloatField`` form field and ``DecimalField`` model and form fields
     85    are new in the development version.
     86
     87As you might expect, the ``ForeignKey`` and ``ManyToManyField`` model field
     88types are special cases:
     89
     90    * ``ForeignKey`` is represented by ``django.newforms.ModelChoiceField``,
     91      which is a ``ChoiceField`` whose choices are a model ``QuerySet``.
     92
     93    * ``ManyToManyField`` is represented by
     94      ``django.newforms.ModelMultipleChoiceField``, which is a
     95      ``MultipleChoiceField`` whose choices are a model ``QuerySet``.
     96
     97In addition, each generated form field has attributes set as follows:
     98
     99    * If the model field has ``blank=True``, then ``required`` is set to
     100      ``False`` on the form field. Otherwise, ``required=True``.
     101
     102    * The form field's ``label`` is set to the ``verbose_name`` of the model
     103      field, with the first character capitalized.
     104
     105    * The form field's ``help_text`` is set to the ``help_text`` of the model
     106      field.
     107
     108    * If the model field has ``choices`` set, then the form field's ``widget``
     109      will be set to ``Select``, with choices coming from the model field's
     110      ``choices``. The choices will normally include the blank choice which is
     111      selected by default. If the field is required, this forces the user to
     112      make a selection. The blank choice will not be included if the model
     113      field has ``blank=False`` and an explicit ``default`` value (the
     114      ``default`` value will be initially selected instead).
     115
     116Finally, note that you can override the form field used for a given model
     117field. See "Overriding the default field types" below.
     118
     119A full example
     120--------------
     121
     122Consider this set of models::
     123
     124    from django.db import models
     125
     126    TITLE_CHOICES = (
     127        ('MR', 'Mr.'),
     128        ('MRS', 'Mrs.'),
     129        ('MS', 'Ms.'),
     130    )
     131
     132    class Author(models.Model):
     133        name = models.CharField(max_length=100)
     134        title = models.CharField(max_length=3, choices=TITLE_CHOICES)
     135        birth_date = models.DateField(blank=True, null=True)
     136
     137        def __unicode__(self):
     138            return self.name
     139
     140    class Book(models.Model):
     141        name = models.CharField(max_length=100)
     142        authors = models.ManyToManyField(Author)
     143
     144    class AuthorForm(ModelForm):
     145        class Meta:
     146            model = Author
     147
     148    class BookForm(ModelForm):
     149        class Meta:
     150            model = Book
     151
     152With these models, the ``ModelForm`` subclasses above would be roughly
     153equivalent to this (the only difference being the ``save()`` method, which
     154we'll discuss in a moment.)::
     155
     156    class AuthorForm(forms.Form):
     157        name = forms.CharField(max_length=100)
     158        title = forms.CharField(max_length=3,
     159                    widget=forms.Select(choices=TITLE_CHOICES))
     160        birth_date = forms.DateField(required=False)
     161
     162    class BookForm(forms.Form):
     163        name = forms.CharField(max_length=100)
     164        authors = forms.ModelMultipleChoiceField(queryset=Author.objects.all())
     165
     166The ``save()`` method
     167---------------------
     168
     169Every form produced by ``ModelForm`` also has a ``save()`` method. This
     170method creates and saves a database object from the data bound to the form.
     171A subclass of ``ModelForm`` also requires a model instance as the first
     172arument to its constructor. For example::
     173
     174    # Create a form instance from POST data.
     175    >>> a = Article()
     176    >>> f = ArticleForm(a, request.POST)
     177
     178    # Save a new Article object from the form's data.
     179    >>> new_article = f.save()
     180
     181Note that ``save()`` will raise a ``ValueError`` if the data in the form
     182doesn't validate -- i.e., ``if form.errors``.
     183
     184This ``save()`` method accepts an optional ``commit`` keyword argument, which
     185accepts either ``True`` or ``False``. If you call ``save()`` with
     186``commit=False``, then it will return an object that hasn't yet been saved to
     187the database. In this case, it's up to you to call ``save()`` on the resulting
     188model instance. This is useful if you want to do custom processing on the
     189object before saving it. ``commit`` is ``True`` by default.
     190
     191Another side effect of using ``commit=False`` is seen when your model has
     192a many-to-many relation with another model. If your model has a many-to-many
     193relation and you specify ``commit=False`` when you save a form, Django cannot
     194immediately save the form data for the many-to-many relation. This is because
     195it isn't possible to save many-to-many data for an instance until the instance
     196exists in the database.
     197
     198To work around this problem, every time you save a form using ``commit=False``,
     199Django adds a ``save_m2m()`` method to your ``ModelForm`` subclass. After
     200you've manually saved the instance produced by the form, you can invoke
     201``save_m2m()`` to save the many-to-many form data. For example::
     202
     203    # Create a form instance with POST data.
     204    >>> a = Author()
     205    >>> f = AuthorForm(a, request.POST)
     206
     207    # Create, but don't save the new author instance.
     208    >>> new_author = f.save(commit=False)
     209
     210    # Modify the author in some way.
     211    >>> new_author.some_field = 'some_value'
     212
     213    # Save the new instance.
     214    >>> new_author.save()
     215
     216    # Now, save the many-to-many data for the form.
     217    >>> f.save_m2m()
     218
     219Calling ``save_m2m()`` is only required if you use ``save(commit=False)``.
     220When you use a simple ``save()`` on a form, all data -- including
     221many-to-many data -- is saved without the need for any additional method calls.
     222For example::
     223
     224    # Create a form instance with POST data.
     225    >>> a = Author()
     226    >>> f = AuthorForm(a, request.POST)
     227
     228    # Create and save the new author instance. There's no need to do anything else.
     229    >>> new_author = f.save()
     230
     231Using a subset of fields on the form
     232------------------------------------
     233
     234In some cases, you may not want all the model fields to appear on the generated
     235form. There are three ways of telling ``ModelForm`` to use only a subset of the
     236model fields:
     237
     238    1. Set ``editable=False`` on the model field. As a result, *any* form
     239       created from the model via ``ModelForm`` will not include that
     240       field.
     241
     242    2. Use the ``fields`` attribute of the ``ModelForm``'s inner ``Meta`` class.
     243       This attribute, if given, should be a list of field names to include in
     244       the form.
     245
     246    3. Use the ``exclude`` attribute of the ``ModelForm``'s inner ``Meta`` class.
     247       This attribute, if given, should be a list of field names to exclude
     248       the form.
     249
     250       For example, if you want a form for the ``Author`` model (defined above)
     251       that includes only the ``name`` and ``title`` fields, you would specify
     252       ``fields`` or  ``exclude`` like this::
     253
     254          class PartialAuthorForm(ModelForm):
     255              class Meta:
     256                  model = Author
     257                  fields = ('name', 'title')
     258
     259          class PartialAuthorForm(ModelForm):
     260              class Meta:
     261                  model = Author
     262                  exclude = ('birth_date',)
     263
     264        Since the Author model has only 3 fields, 'name', 'title', and
     265        'birth_date', the forms above will contain exactly the same fields.
     266
     267.. note::
     268
     269    If you specify ``fields`` or ``exclude`` when creating a form with
     270    ``ModelForm``, then the fields that are not in the resulting form will not
     271    be set by the form's ``save()`` method. Django will prevent any attempt to
     272    save an incomplete model, so if the model does not allow the missing fields
     273    to be empty, and does not provide a default value for the missing fields,
     274    any attempt to ``save()`` a ``ModelForm`` with missing fields will fail.
     275    To avoid this failure, you must instantiate your model with initial values
     276    for the missing, but required fields, or use ``save(commit=False)`` and
     277    manually set anyextra required fields::
     278   
     279        instance = Instance(requiured_field='value')
     280        form = InstanceForm(instance, request.POST)
     281        new_instance = form.save()
     282
     283        instance = form.save(commit=False)
     284        instance.required_field = 'new value'
     285        new_instance = instance.save()
     286
     287    See the `section on saving forms`_ for more details on using
     288    ``save(commit=False)``.
     289
     290.. _section on saving forms: `The save() method`_
     291
     292Overriding the default field types
     293----------------------------------
     294
     295The default field types, as described in the "Field types" table above, are
     296sensible defaults; if you have a ``DateField`` in your model, chances are you'd
     297want that to be represented as a ``DateField`` in your form. But
     298``ModelForm`` gives you the flexibility of changing the form field type
     299for a given model field. You do this by declaratively specifying fields like
     300you would in a regular ``Form``. Declared fields will override the default
     301ones generated by using the ``model`` attribute.
     302
     303For example, if you wanted to use ``MyDateFormField`` for the ``pub_date``
     304field, you could do the following::
     305
     306    >>> class ArticleForm(ModelForm):
     307    ...     pub_date = MyDateFormField()
     308    ...
     309    ...     class Meta:
     310    ...         model = Article
  • docs/newforms.txt

    diff --git a/docs/newforms.txt b/docs/newforms.txt
    index f26afcb..75573ac 100644
    a b You can then use this field whenever you have a form that requires a comment::  
    17681768Generating forms for models
    17691769===========================
    17701770
    1771 If you're building a database-driven app, chances are you'll have forms that
    1772 map closely to Django models. For instance, you might have a ``BlogComment``
    1773 model, and you want to create a form that lets people submit comments. In this
    1774 case, it would be redundant to define the field types in your form, because
    1775 you've already defined the fields in your model.
     1771The prefered way of generating forms that work with models is explained in the
     1772`ModelForms documentation`_.
    17761773
    1777 For this reason, Django provides a few helper functions that let you create a
    1778 ``Form`` class from a Django model.
     1774Looking for the ``form_for_model`` and ``form_for_instance`` documentation?
     1775They've been deprecated, but you can still `view the documentation`_.
    17791776
    1780 ``form_for_model()``
    1781 --------------------
    1782 
    1783 The method ``django.newforms.form_for_model()`` creates a form based on the
    1784 definition of a specific model. Pass it the model class, and it will return a
    1785 ``Form`` class that contains a form field for each model field.
    1786 
    1787 For example::
    1788 
    1789     >>> from django.newforms import form_for_model
    1790 
    1791     # Create the form class.
    1792     >>> ArticleForm = form_for_model(Article)
    1793 
    1794     # Create an empty form instance.
    1795     >>> f = ArticleForm()
    1796 
    1797 It bears repeating that ``form_for_model()`` takes the model *class*, not a
    1798 model instance, and it returns a ``Form`` *class*, not a ``Form`` instance.
    1799 
    1800 Field types
    1801 ~~~~~~~~~~~
    1802 
    1803 The generated ``Form`` class will have a form field for every model field. Each
    1804 model field has a corresponding default form field. For example, a
    1805 ``CharField`` on a model is represented as a ``CharField`` on a form. A
    1806 model ``ManyToManyField`` is represented as a ``MultipleChoiceField``. Here is
    1807 the full list of conversions:
    1808 
    1809     ===============================  ========================================
    1810     Model field                      Form field
    1811     ===============================  ========================================
    1812     ``AutoField``                    Not represented in the form
    1813     ``BooleanField``                 ``BooleanField``
    1814     ``CharField``                    ``CharField`` with ``max_length`` set to
    1815                                      the model field's ``max_length``
    1816     ``CommaSeparatedIntegerField``   ``CharField``
    1817     ``DateField``                    ``DateField``
    1818     ``DateTimeField``                ``DateTimeField``
    1819     ``DecimalField``                 ``DecimalField``
    1820     ``EmailField``                   ``EmailField``
    1821     ``FileField``                    ``FileField``
    1822     ``FilePathField``                ``CharField``
    1823     ``FloatField``                   ``FloatField``
    1824     ``ForeignKey``                   ``ModelChoiceField`` (see below)
    1825     ``ImageField``                   ``ImageField``
    1826     ``IntegerField``                 ``IntegerField``
    1827     ``IPAddressField``               ``IPAddressField``
    1828     ``ManyToManyField``              ``ModelMultipleChoiceField`` (see
    1829                                      below)
    1830     ``NullBooleanField``             ``CharField``
    1831     ``PhoneNumberField``             ``USPhoneNumberField``
    1832                                      (from ``django.contrib.localflavor.us``)
    1833     ``PositiveIntegerField``         ``IntegerField``
    1834     ``PositiveSmallIntegerField``    ``IntegerField``
    1835     ``SlugField``                    ``CharField``
    1836     ``SmallIntegerField``            ``IntegerField``
    1837     ``TextField``                    ``CharField`` with ``widget=Textarea``
    1838     ``TimeField``                    ``TimeField``
    1839     ``URLField``                     ``URLField`` with ``verify_exists`` set
    1840                                      to the model field's ``verify_exists``
    1841     ``USStateField``                 ``CharField`` with
    1842                                      ``widget=USStateSelect``
    1843                                      (``USStateSelect`` is from
    1844                                      ``django.contrib.localflavor.us``)
    1845     ``XMLField``                     ``CharField`` with ``widget=Textarea``
    1846     ===============================  ========================================
    1847 
    1848 
    1849 .. note::
    1850     The ``FloatField`` form field and ``DecimalField`` model and form fields
    1851     are new in the development version.
    1852 
    1853 As you might expect, the ``ForeignKey`` and ``ManyToManyField`` model field
    1854 types are special cases:
    1855 
    1856     * ``ForeignKey`` is represented by ``django.newforms.ModelChoiceField``,
    1857       which is a ``ChoiceField`` whose choices are a model ``QuerySet``.
    1858 
    1859     * ``ManyToManyField`` is represented by
    1860       ``django.newforms.ModelMultipleChoiceField``, which is a
    1861       ``MultipleChoiceField`` whose choices are a model ``QuerySet``.
    1862 
    1863 In addition, each generated form field has attributes set as follows:
    1864 
    1865     * If the model field has ``blank=True``, then ``required`` is set to
    1866       ``False`` on the form field. Otherwise, ``required=True``.
    1867 
    1868     * The form field's ``label`` is set to the ``verbose_name`` of the model
    1869       field, with the first character capitalized.
    1870 
    1871     * The form field's ``help_text`` is set to the ``help_text`` of the model
    1872       field.
    1873 
    1874     * If the model field has ``choices`` set, then the form field's ``widget``
    1875       will be set to ``Select``, with choices coming from the model field's
    1876       ``choices``. The choices will normally include the blank choice which is
    1877       selected by default. If the field is required, this forces the user to
    1878       make a selection. The blank choice will not be included if the model
    1879       field has ``blank=False`` and an explicit ``default`` value (the
    1880       ``default`` value will be initially selected instead).
    1881 
    1882 Finally, note that you can override the form field used for a given model
    1883 field. See "Overriding the default field types" below.
    1884 
    1885 A full example
    1886 ~~~~~~~~~~~~~~
    1887 
    1888 Consider this set of models::
    1889 
    1890     from django.db import models
    1891 
    1892     TITLE_CHOICES = (
    1893         ('MR', 'Mr.'),
    1894         ('MRS', 'Mrs.'),
    1895         ('MS', 'Ms.'),
    1896     )
    1897 
    1898     class Author(models.Model):
    1899         name = models.CharField(max_length=100)
    1900         title = models.CharField(max_length=3, choices=TITLE_CHOICES)
    1901         birth_date = models.DateField(blank=True, null=True)
    1902 
    1903         def __unicode__(self):
    1904             return self.name
    1905 
    1906     class Book(models.Model):
    1907         name = models.CharField(max_length=100)
    1908         authors = models.ManyToManyField(Author)
    1909 
    1910 With these models, a call to ``form_for_model(Author)`` would return a ``Form``
    1911 class equivalent to this::
    1912 
    1913     class AuthorForm(forms.Form):
    1914         name = forms.CharField(max_length=100)
    1915         title = forms.CharField(max_length=3,
    1916                     widget=forms.Select(choices=TITLE_CHOICES))
    1917         birth_date = forms.DateField(required=False)
    1918 
    1919 A call to ``form_for_model(Book)`` would return a ``Form`` class equivalent to
    1920 this::
    1921 
    1922     class BookForm(forms.Form):
    1923         name = forms.CharField(max_length=100)
    1924         authors = forms.ModelMultipleChoiceField(queryset=Author.objects.all())
    1925 
    1926 The ``save()`` method
    1927 ~~~~~~~~~~~~~~~~~~~~~
    1928 
    1929 Every form produced by ``form_for_model()`` also has a ``save()`` method. This
    1930 method creates and saves a database object from the data bound to the form. For
    1931 example::
    1932 
    1933     # Create a form instance from POST data.
    1934     >>> f = ArticleForm(request.POST)
    1935 
    1936     # Save a new Article object from the form's data.
    1937     >>> new_article = f.save()
    1938 
    1939 Note that ``save()`` will raise a ``ValueError`` if the data in the form
    1940 doesn't validate -- i.e., ``if form.errors``.
    1941 
    1942 This ``save()`` method accepts an optional ``commit`` keyword argument, which
    1943 accepts either ``True`` or ``False``. If you call ``save()`` with
    1944 ``commit=False``, then it will return an object that hasn't yet been saved to
    1945 the database. In this case, it's up to you to call ``save()`` on the resulting
    1946 model instance. This is useful if you want to do custom processing on the
    1947 object before saving it. ``commit`` is ``True`` by default.
    1948 
    1949 Another side effect of using ``commit=False`` is seen when your model has
    1950 a many-to-many relation with another model. If your model has a many-to-many
    1951 relation and you specify ``commit=False`` when you save a form, Django cannot
    1952 immediately save the form data for the many-to-many relation. This is because
    1953 it isn't possible to save many-to-many data for an instance until the instance
    1954 exists in the database.
    1955 
    1956 To work around this problem, every time you save a form using ``commit=False``,
    1957 Django adds a ``save_m2m()`` method to the form created by ``form_for_model``.
    1958 After you've manually saved the instance produced by the form, you can invoke
    1959 ``save_m2m()`` to save the many-to-many form data. For example::
    1960 
    1961     # Create a form instance with POST data.
    1962     >>> f = AuthorForm(request.POST)
    1963 
    1964     # Create, but don't save the new author instance.
    1965     >>> new_author = f.save(commit=False)
    1966 
    1967     # Modify the author in some way.
    1968     >>> new_author.some_field = 'some_value'
    1969 
    1970     # Save the new instance.
    1971     >>> new_author.save()
    1972 
    1973     # Now, save the many-to-many data for the form.
    1974     >>> f.save_m2m()
    1975 
    1976 Calling ``save_m2m()`` is only required if you use ``save(commit=False)``.
    1977 When you use a simple ``save()`` on a form, all data -- including
    1978 many-to-many data -- is saved without the need for any additional method calls.
    1979 For example::
    1980 
    1981     # Create a form instance with POST data.
    1982     >>> f = AuthorForm(request.POST)
    1983 
    1984     # Create and save the new author instance. There's no need to do anything else.
    1985     >>> new_author = f.save()
    1986 
    1987 Using an alternate base class
    1988 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    1989 
    1990 If you want to add custom methods to the form generated by
    1991 ``form_for_model()``, write a class that extends ``django.newforms.BaseForm``
    1992 and contains your custom methods. Then, use the ``form`` argument to
    1993 ``form_for_model()`` to tell it to use your custom form as its base class.
    1994 For example::
    1995 
    1996     # Create the new base class.
    1997     >>> class MyBase(BaseForm):
    1998     ...     def my_method(self):
    1999     ...         # Do whatever the method does
    2000 
    2001     # Create the form class with a different base class.
    2002     >>> ArticleForm = form_for_model(Article, form=MyBase)
    2003 
    2004     # Instantiate the form.
    2005     >>> f = ArticleForm()
    2006 
    2007     # Use the base class method.
    2008     >>> f.my_method()
    2009 
    2010 Using a subset of fields on the form
    2011 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    2012 
    2013 **New in Django development version**
    2014 
    2015 In some cases, you may not want all the model fields to appear on the generated
    2016 form. There are two ways of telling ``form_for_model()`` to use only a subset
    2017 of the model fields:
    2018 
    2019     1. Set ``editable=False`` on the model field. As a result, *any* form
    2020        created from the model via ``form_for_model()`` will not include that
    2021        field.
    2022 
    2023     2. Use the ``fields`` argument to ``form_for_model()``. This argument, if
    2024        given, should be a list of field names to include in the form.
    2025 
    2026        For example, if you want a form for the ``Author`` model (defined above)
    2027        that includes only the ``name`` and ``title`` fields, you would specify
    2028        ``fields`` like this::
    2029 
    2030            PartialArticleForm = form_for_model(Author, fields=('name', 'title'))
    2031 
    2032 .. note::
    2033 
    2034     If you specify ``fields`` when creating a form with ``form_for_model()``,
    2035     then the fields that are *not* specified will not be set by the form's
    2036     ``save()`` method. Django will prevent any attempt to save an incomplete
    2037     model, so if the model does not allow the missing fields to be empty, and
    2038     does not provide a default value for the missing fields, any attempt to
    2039     ``save()`` a ``form_for_model`` with missing fields will fail. To avoid
    2040     this failure, you must use ``save(commit=False)`` and manually set any
    2041     extra required fields::
    2042 
    2043         instance = form.save(commit=False)
    2044         instance.required_field = 'new value'
    2045         instance.save()
    2046 
    2047     See the `section on saving forms`_ for more details on using
    2048     ``save(commit=False)``.
    2049 
    2050 .. _section on saving forms: `The save() method`_
    2051 
    2052 Overriding the default field types
    2053 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    2054 
    2055 The default field types, as described in the "Field types" table above, are
    2056 sensible defaults; if you have a ``DateField`` in your model, chances are you'd
    2057 want that to be represented as a ``DateField`` in your form. But
    2058 ``form_for_model()`` gives you the flexibility of changing the form field type
    2059 for a given model field. You do this by specifying a **formfield callback**.
    2060 
    2061 A formfield callback is a function that, when provided with a model field,
    2062 returns a form field instance. When constructing a form, ``form_for_model()``
    2063 asks the formfield callback to provide form field types.
    2064 
    2065 By default, ``form_for_model()`` calls the ``formfield()`` method on the model
    2066 field::
    2067 
    2068     def default_callback(field, **kwargs):
    2069         return field.formfield(**kwargs)
    2070 
    2071 The ``kwargs`` are any keyword arguments that might be passed to the form
    2072 field, such as ``required=True`` or ``label='Foo'``.
    2073 
    2074 For example, if you wanted to use ``MyDateFormField`` for any ``DateField``
    2075 field on the model, you could define the callback::
    2076 
    2077     >>> def my_callback(field, **kwargs):
    2078     ...     if isinstance(field, models.DateField):
    2079     ...         return MyDateFormField(**kwargs)
    2080     ...     else:
    2081     ...         return field.formfield(**kwargs)
    2082 
    2083     >>> ArticleForm = form_for_model(Article, formfield_callback=my_callback)
    2084 
    2085 Note that your callback needs to handle *all* possible model field types, not
    2086 just the ones that you want to behave differently to the default. That's why
    2087 this example has an ``else`` clause that implements the default behavior.
    2088 
    2089 .. warning::
    2090     The field that is passed into the ``formfield_callback`` function in
    2091     ``form_for_model()`` and ``form_for_instance`` is the field instance from
    2092     your model's class. You **must not** alter that object at all; treat it
    2093     as read-only!
    2094 
    2095     If you make any alterations to that object, it will affect any future
    2096     users of the model class, because you will have changed the field object
    2097     used to construct the class. This is almost certainly what you don't want
    2098     to have happen.
    2099 
    2100 Finding the model associated with a form
    2101 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    2102 
    2103 The model class that was used to construct the form is available
    2104 using the ``_model`` property of the generated form::
    2105 
    2106     >>> ArticleForm = form_for_model(Article)
    2107     >>> ArticleForm._model
    2108     <class 'myapp.models.Article'>
    2109 
    2110 ``form_for_instance()``
    2111 -----------------------
    2112 
    2113 ``form_for_instance()`` is like ``form_for_model()``, but it takes a model
    2114 instance instead of a model class::
    2115 
    2116     # Create an Author.
    2117     >>> a = Author(name='Joe Smith', title='MR', birth_date=None)
    2118     >>> a.save()
    2119 
    2120     # Create a form for this particular Author.
    2121     >>> AuthorForm = form_for_instance(a)
    2122 
    2123     # Instantiate the form.
    2124     >>> f = AuthorForm()
    2125 
    2126 When a form created by ``form_for_instance()`` is created, the initial data
    2127 values for the form fields are drawn from the instance. However, this data is
    2128 not bound to the form. You will need to bind data to the form before the form
    2129 can be saved.
    2130 
    2131 Unlike ``form_for_model()``, a choice field in form created by
    2132 ``form_for_instance()`` will not include the blank choice if the respective
    2133 model field has ``blank=False``. The initial choice is drawn from the instance.
    2134 
    2135 When you call ``save()`` on a form created by ``form_for_instance()``,
    2136 the database instance will be updated. As in ``form_for_model()``, ``save()``
    2137 will raise ``ValueError`` if the data doesn't validate.
    2138 
    2139 ``form_for_instance()`` has ``form``, ``fields`` and ``formfield_callback``
    2140 arguments that behave the same way as they do for ``form_for_model()``.
    2141 
    2142 Let's modify the earlier `contact form`_ view example a little bit. Suppose we
    2143 have a ``Message`` model that holds each contact submission. Something like::
    2144 
    2145     class Message(models.Model):
    2146         subject = models.CharField(max_length=100)
    2147         message = models.TextField()
    2148         sender = models.EmailField()
    2149         cc_myself = models.BooleanField(required=False)
    2150 
    2151 You could use this model to create a form (using ``form_for_model()``). You
    2152 could also use existing ``Message`` instances to create a form for editing
    2153 messages. The earlier_ view can be changed slightly to accept the ``id`` value
    2154 of an existing ``Message`` and present it for editing::
    2155 
    2156     def contact_edit(request, msg_id):
    2157         # Create the form from the message id.
    2158         message = get_object_or_404(Message, id=msg_id)
    2159         ContactForm = form_for_instance(message)
    2160 
    2161         if request.method == 'POST':
    2162             form = ContactForm(request.POST)
    2163             if form.is_valid():
    2164                 form.save()
    2165                 return HttpResponseRedirect('/url/on_success/')
    2166         else:
    2167             form = ContactForm()
    2168         return render_to_response('contact.html', {'form': form})
    2169 
    2170 Aside from how we create the ``ContactForm`` class here, the main point to
    2171 note is that the form display in the ``GET`` branch of the function
    2172 will use the values from the ``message`` instance as initial values for the
    2173 form field.
    2174 
    2175 .. _contact form: `Simple view example`_
    2176 .. _earlier: `Simple view example`_
    2177 
    2178 When should you use ``form_for_model()`` and ``form_for_instance()``?
    2179 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    2180 
    2181 The ``form_for_model()`` and ``form_for_instance()`` functions are meant to be
    2182 shortcuts for the common case. If you want to create a form whose fields map to
    2183 more than one model, or a form that contains fields that *aren't* on a model,
    2184 you shouldn't use these shortcuts. Creating a ``Form`` class the "long" way
    2185 isn't that difficult, after all.
     1777.. _ModelForms documentation: ../modelforms/
     1778.. _view the documentation: ../form_for_model/
    21861779
    21871780More coming soon
    21881781================
  • new file tests/modeltests/model_forms_new/models.py

    diff --git a/tests/modeltests/model_forms_new/__init__.py b/tests/modeltests/model_forms_new/__init__.py
    new file mode 100644
    index 0000000..e69de29
    diff --git a/tests/modeltests/model_forms_new/models.py b/tests/modeltests/model_forms_new/models.py
    new file mode 100644
    index 0000000..bd611ed
    - +  
     1"""
     2XX. Generating HTML forms from models
     3
     4This is mostly just a reworking of the form_for_model/form_for_instance tests
     5to use ModelForm. As such, the text may not make sense in all cases, and the
     6examples are probably a poor fit for the ModelForm syntax. In other words,
     7most of these tests should be rewritten.
     8"""
     9
     10from django.db import models
     11
     12ARTICLE_STATUS = (
     13    (1, 'Draft'),
     14    (2, 'Pending'),
     15    (3, 'Live'),
     16)
     17
     18class Category(models.Model):
     19    name = models.CharField(max_length=20)
     20    slug = models.SlugField(max_length=20)
     21    url = models.CharField('The URL', max_length=40)
     22
     23    def __unicode__(self):
     24        return self.name
     25
     26class Writer(models.Model):
     27    name = models.CharField(max_length=50, help_text='Use both first and last names.')
     28
     29    def __unicode__(self):
     30        return self.name
     31
     32class Article(models.Model):
     33    headline = models.CharField(max_length=50)
     34    slug = models.SlugField()
     35    pub_date = models.DateField()
     36    created = models.DateField(editable=False)
     37    writer = models.ForeignKey(Writer)
     38    article = models.TextField()
     39    categories = models.ManyToManyField(Category, blank=True)
     40    status = models.IntegerField(choices=ARTICLE_STATUS, blank=True, null=True)
     41
     42    def save(self):
     43        import datetime
     44        if not self.id:
     45            self.created = datetime.date.today()
     46        return super(Article, self).save()
     47
     48    def __unicode__(self):
     49        return self.headline
     50
     51class PhoneNumber(models.Model):
     52    phone = models.PhoneNumberField()
     53    description = models.CharField(max_length=20)
     54
     55    def __unicode__(self):
     56        return self.phone
     57
     58__test__ = {'API_TESTS': """
     59>>> from django import newforms as forms
     60>>> from django.newforms.models import ModelForm
     61
     62The bare bones, absolutely nothing custom, basic case.
     63
     64>>> class CategoryForm(ModelForm):
     65...     class Meta:
     66...         model = Category
     67>>> CategoryForm.base_fields.keys()
     68['name', 'slug', 'url']
     69
     70
     71Extra fields.
     72
     73>>> class CategoryForm(ModelForm):
     74...     some_extra_field = forms.BooleanField()
     75...
     76...     class Meta:
     77...         model = Category
     78
     79>>> CategoryForm.base_fields.keys()
     80['name', 'slug', 'url', 'some_extra_field']
     81
     82
     83Replacing a field.
     84
     85>>> class CategoryForm(ModelForm):
     86...     url = forms.BooleanField()
     87...
     88...     class Meta:
     89...         model = Category
     90
     91>>> CategoryForm.base_fields['url'].__class__
     92<class 'django.newforms.fields.BooleanField'>
     93
     94
     95Using 'fields'.
     96
     97>>> class CategoryForm(ModelForm):
     98...
     99...     class Meta:
     100...         model = Category
     101...         fields = ['url']
     102
     103>>> CategoryForm.base_fields.keys()
     104['url']
     105
     106
     107Using 'exclude'
     108
     109>>> class CategoryForm(ModelForm):
     110...
     111...     class Meta:
     112...         model = Category
     113...         exclude = ['url']
     114
     115>>> CategoryForm.base_fields.keys()
     116['name', 'slug']
     117
     118
     119Using 'fields' *and* 'exclude'. Not sure why you'd want to do this, but uh,
     120"be liberal in what you accept" and all.
     121
     122>>> class CategoryForm(ModelForm):
     123...
     124...     class Meta:
     125...         model = Category
     126...         fields = ['name', 'url']
     127...         exclude = ['url']
     128
     129>>> CategoryForm.base_fields.keys()
     130['name']
     131
     132Don't allow more than one 'model' defenition in the inheritance hierarchy.
     133Technically, it would generate a valid form, but the fact that the resulting
     134save method won't deal with multiple objects is likely to trip up people not
     135familiar with the mechanics.
     136
     137>>> class CategoryForm(ModelForm):
     138...     class Meta:
     139...         model = Category
     140
     141>>> class BadForm(CategoryForm):
     142...     class Meta:
     143...         model = Article
     144Traceback (most recent call last):
     145...
     146ImproperlyConfigured: BadForm defines more than one model.
     147
     148>>> class ArticleForm(ModelForm):
     149...     class Meta:
     150...         model = Article
     151
     152>>> class BadForm(ArticleForm, CategoryForm):
     153...     pass
     154Traceback (most recent call last):
     155...
     156ImproperlyConfigured: BadForm's base classes define more than one model.
     157
     158
     159# Old form_for_x tests #######################################################
     160
     161>>> from django.newforms import ModelForm, CharField
     162>>> import datetime
     163
     164>>> Category.objects.all()
     165[]
     166
     167>>> class CategoryForm(ModelForm):
     168...     class Meta:
     169...         model = Category
     170>>> f = CategoryForm(Category())
     171>>> print f
     172<tr><th><label for="id_name">Name:</label></th><td><input id="id_name" type="text" name="name" maxlength="20" /></td></tr>
     173<tr><th><label for="id_slug">Slug:</label></th><td><input id="id_slug" type="text" name="slug" maxlength="20" /></td></tr>
     174<tr><th><label for="id_url">The URL:</label></th><td><input id="id_url" type="text" name="url" maxlength="40" /></td></tr>
     175>>> print f.as_ul()
     176<li><label for="id_name">Name:</label> <input id="id_name" type="text" name="name" maxlength="20" /></li>
     177<li><label for="id_slug">Slug:</label> <input id="id_slug" type="text" name="slug" maxlength="20" /></li>
     178<li><label for="id_url">The URL:</label> <input id="id_url" type="text" name="url" maxlength="40" /></li>
     179>>> print f['name']
     180<input id="id_name" type="text" name="name" maxlength="20" />
     181
     182>>> f = CategoryForm(Category(), auto_id=False)
     183>>> print f.as_ul()
     184<li>Name: <input type="text" name="name" maxlength="20" /></li>
     185<li>Slug: <input type="text" name="slug" maxlength="20" /></li>
     186<li>The URL: <input type="text" name="url" maxlength="40" /></li>
     187
     188>>> f = CategoryForm(Category(), {'name': 'Entertainment', 'slug': 'entertainment', 'url': 'entertainment'})
     189>>> f.is_valid()
     190True
     191>>> f.cleaned_data
     192{'url': u'entertainment', 'name': u'Entertainment', 'slug': u'entertainment'}
     193>>> obj = f.save()
     194>>> obj
     195<Category: Entertainment>
     196>>> Category.objects.all()
     197[<Category: Entertainment>]
     198
     199>>> f = CategoryForm(Category(), {'name': "It's a test", 'slug': 'its-test', 'url': 'test'})
     200>>> f.is_valid()
     201True
     202>>> f.cleaned_data
     203{'url': u'test', 'name': u"It's a test", 'slug': u'its-test'}
     204>>> obj = f.save()
     205>>> obj
     206<Category: It's a test>
     207>>> Category.objects.order_by('name')
     208[<Category: Entertainment>, <Category: It's a test>]
     209
     210If you call save() with commit=False, then it will return an object that
     211hasn't yet been saved to the database. In this case, it's up to you to call
     212save() on the resulting model instance.
     213>>> f = CategoryForm(Category(), {'name': 'Third test', 'slug': 'third-test', 'url': 'third'})
     214>>> f.is_valid()
     215True
     216>>> f.cleaned_data
     217{'url': u'third', 'name': u'Third test', 'slug': u'third-test'}
     218>>> obj = f.save(commit=False)
     219>>> obj
     220<Category: Third test>
     221>>> Category.objects.order_by('name')
     222[<Category: Entertainment>, <Category: It's a test>]
     223>>> obj.save()
     224>>> Category.objects.order_by('name')
     225[<Category: Entertainment>, <Category: It's a test>, <Category: Third test>]
     226
     227If you call save() with invalid data, you'll get a ValueError.
     228>>> f = CategoryForm(Category(), {'name': '', 'slug': '', 'url': 'foo'})
     229>>> f.errors
     230{'name': [u'This field is required.'], 'slug': [u'This field is required.']}
     231>>> f.cleaned_data
     232Traceback (most recent call last):
     233...
     234AttributeError: 'CategoryForm' object has no attribute 'cleaned_data'
     235>>> f.save()
     236Traceback (most recent call last):
     237...
     238ValueError: The Category could not be created because the data didn't validate.
     239>>> f = CategoryForm(Category(), {'name': '', 'slug': '', 'url': 'foo'})
     240>>> f.save()
     241Traceback (most recent call last):
     242...
     243ValueError: The Category could not be created because the data didn't validate.
     244
     245Create a couple of Writers.
     246>>> w = Writer(name='Mike Royko')
     247>>> w.save()
     248>>> w = Writer(name='Bob Woodward')
     249>>> w.save()
     250
     251ManyToManyFields are represented by a MultipleChoiceField, ForeignKeys and any
     252fields with the 'choices' attribute are represented by a ChoiceField.
     253>>> class ArticleForm(ModelForm):
     254...     class Meta:
     255...         model = Article
     256>>> f = ArticleForm(Article(), auto_id=False)
     257>>> print f
     258<tr><th>Headline:</th><td><input type="text" name="headline" maxlength="50" /></td></tr>
     259<tr><th>Slug:</th><td><input type="text" name="slug" maxlength="50" /></td></tr>
     260<tr><th>Pub date:</th><td><input type="text" name="pub_date" /></td></tr>
     261<tr><th>Writer:</th><td><select name="writer">
     262<option value="" selected="selected">---------</option>
     263<option value="1">Mike Royko</option>
     264<option value="2">Bob Woodward</option>
     265</select></td></tr>
     266<tr><th>Article:</th><td><textarea rows="10" cols="40" name="article"></textarea></td></tr>
     267<tr><th>Status:</th><td><select name="status">
     268<option value="" selected="selected">---------</option>
     269<option value="1">Draft</option>
     270<option value="2">Pending</option>
     271<option value="3">Live</option>
     272</select></td></tr>
     273<tr><th>Categories:</th><td><select multiple="multiple" name="categories">
     274<option value="1">Entertainment</option>
     275<option value="2">It&#39;s a test</option>
     276<option value="3">Third test</option>
     277</select><br /> Hold down "Control", or "Command" on a Mac, to select more than one.</td></tr>
     278
     279You can restrict a form to a subset of the complete list of fields
     280by providing a 'fields' argument. If you try to save a
     281model created with such a form, you need to ensure that the fields
     282that are _not_ on the form have default values, or are allowed to have
     283a value of None. If a field isn't specified on a form, the object created
     284from the form can't provide a value for that field!
     285>>> class PartialArticleForm(ModelForm):
     286...     class Meta:
     287...         model = Article
     288...         fields = ('headline','pub_date')
     289>>> f = PartialArticleForm(Article(), auto_id=False)
     290>>> print f
     291<tr><th>Headline:</th><td><input type="text" name="headline" maxlength="50" /></td></tr>
     292<tr><th>Pub date:</th><td><input type="text" name="pub_date" /></td></tr>
     293
     294Use form_for_instance to create a Form from a model instance. The difference
     295between this Form and one created via form_for_model is that the object's
     296current values are inserted as 'initial' data in each Field.
     297>>> w = Writer.objects.get(name='Mike Royko')
     298>>> class RoykoForm(ModelForm):
     299...     class Meta:
     300...         model = Writer
     301>>> f = RoykoForm(w, auto_id=False)
     302>>> print f
     303<tr><th>Name:</th><td><input type="text" name="name" value="Mike Royko" maxlength="50" /><br />Use both first and last names.</td></tr>
     304
     305>>> art = Article(headline='Test article', slug='test-article', pub_date=datetime.date(1988, 1, 4), writer=w, article='Hello.')
     306>>> art.save()
     307>>> art.id
     3081
     309>>> class TestArticleForm(ModelForm):
     310...     class Meta:
     311...         model = Article
     312>>> f = TestArticleForm(art, auto_id=False)
     313>>> print f.as_ul()
     314<li>Headline: <input type="text" name="headline" value="Test article" maxlength="50" /></li>
     315<li>Slug: <input type="text" name="slug" value="test-article" maxlength="50" /></li>
     316<li>Pub date: <input type="text" name="pub_date" value="1988-01-04" /></li>
     317<li>Writer: <select name="writer">
     318<option value="">---------</option>
     319<option value="1" selected="selected">Mike Royko</option>
     320<option value="2">Bob Woodward</option>
     321</select></li>
     322<li>Article: <textarea rows="10" cols="40" name="article">Hello.</textarea></li>
     323<li>Status: <select name="status">
     324<option value="" selected="selected">---------</option>
     325<option value="1">Draft</option>
     326<option value="2">Pending</option>
     327<option value="3">Live</option>
     328</select></li>
     329<li>Categories: <select multiple="multiple" name="categories">
     330<option value="1">Entertainment</option>
     331<option value="2">It&#39;s a test</option>
     332<option value="3">Third test</option>
     333</select>  Hold down "Control", or "Command" on a Mac, to select more than one.</li>
     334>>> f = TestArticleForm(art, {'headline': u'Test headline', 'slug': 'test-headline', 'pub_date': u'1984-02-06', 'writer': u'1', 'article': 'Hello.'})
     335>>> f.is_valid()
     336True
     337>>> test_art = f.save()
     338>>> test_art.id
     3391
     340>>> test_art = Article.objects.get(id=1)
     341>>> test_art.headline
     342u'Test headline'
     343
     344You can create a form over a subset of the available fields
     345by specifying a 'fields' argument to form_for_instance.
     346>>> class PartialArticleForm(ModelForm):
     347...     class Meta:
     348...         model = Article
     349...         fields=('headline', 'slug', 'pub_date')
     350>>> f = PartialArticleForm(art, {'headline': u'New headline', 'slug': 'new-headline', 'pub_date': u'1988-01-04'}, auto_id=False)
     351>>> print f.as_ul()
     352<li>Headline: <input type="text" name="headline" value="New headline" maxlength="50" /></li>
     353<li>Slug: <input type="text" name="slug" value="new-headline" maxlength="50" /></li>
     354<li>Pub date: <input type="text" name="pub_date" value="1988-01-04" /></li>
     355>>> f.is_valid()
     356True
     357>>> new_art = f.save()
     358>>> new_art.id
     3591
     360>>> new_art = Article.objects.get(id=1)
     361>>> new_art.headline
     362u'New headline'
     363
     364Add some categories and test the many-to-many form output.
     365>>> new_art.categories.all()
     366[]
     367>>> new_art.categories.add(Category.objects.get(name='Entertainment'))
     368>>> new_art.categories.all()
     369[<Category: Entertainment>]
     370>>> class TestArticleForm(ModelForm):
     371...     class Meta:
     372...         model = Article
     373>>> f = TestArticleForm(new_art, auto_id=False)
     374>>> print f.as_ul()
     375<li>Headline: <input type="text" name="headline" value="New headline" maxlength="50" /></li>
     376<li>Slug: <input type="text" name="slug" value="new-headline" maxlength="50" /></li>
     377<li>Pub date: <input type="text" name="pub_date" value="1988-01-04" /></li>
     378<li>Writer: <select name="writer">
     379<option value="">---------</option>
     380<option value="1" selected="selected">Mike Royko</option>
     381<option value="2">Bob Woodward</option>
     382</select></li>
     383<li>Article: <textarea rows="10" cols="40" name="article">Hello.</textarea></li>
     384<li>Status: <select name="status">
     385<option value="" selected="selected">---------</option>
     386<option value="1">Draft</option>
     387<option value="2">Pending</option>
     388<option value="3">Live</option>
     389</select></li>
     390<li>Categories: <select multiple="multiple" name="categories">
     391<option value="1" selected="selected">Entertainment</option>
     392<option value="2">It&#39;s a test</option>
     393<option value="3">Third test</option>
     394</select>  Hold down "Control", or "Command" on a Mac, to select more than one.</li>
     395
     396>>> f = TestArticleForm(new_art, {'headline': u'New headline', 'slug': u'new-headline', 'pub_date': u'1988-01-04',
     397...     'writer': u'1', 'article': u'Hello.', 'categories': [u'1', u'2']})
     398>>> new_art = f.save()
     399>>> new_art.id
     4001
     401>>> new_art = Article.objects.get(id=1)
     402>>> new_art.categories.order_by('name')
     403[<Category: Entertainment>, <Category: It's a test>]
     404
     405Now, submit form data with no categories. This deletes the existing categories.
     406>>> f = TestArticleForm(new_art, {'headline': u'New headline', 'slug': u'new-headline', 'pub_date': u'1988-01-04',
     407...     'writer': u'1', 'article': u'Hello.'})
     408>>> new_art = f.save()
     409>>> new_art.id
     4101
     411>>> new_art = Article.objects.get(id=1)
     412>>> new_art.categories.all()
     413[]
     414
     415Create a new article, with categories, via the form.
     416>>> class ArticleForm(ModelForm):
     417...     class Meta:
     418...         model = Article
     419>>> f = ArticleForm(Article(), {'headline': u'The walrus was Paul', 'slug': u'walrus-was-paul', 'pub_date': u'1967-11-01',
     420...     'writer': u'1', 'article': u'Test.', 'categories': [u'1', u'2']})
     421>>> new_art = f.save()
     422>>> new_art.id
     4232
     424>>> new_art = Article.objects.get(id=2)
     425>>> new_art.categories.order_by('name')
     426[<Category: Entertainment>, <Category: It's a test>]
     427
     428Create a new article, with no categories, via the form.
     429>>> class ArticleForm(ModelForm):
     430...     class Meta:
     431...         model = Article
     432>>> f = ArticleForm(Article(), {'headline': u'The walrus was Paul', 'slug': u'walrus-was-paul', 'pub_date': u'1967-11-01',
     433...     'writer': u'1', 'article': u'Test.'})
     434>>> new_art = f.save()
     435>>> new_art.id
     4363
     437>>> new_art = Article.objects.get(id=3)
     438>>> new_art.categories.all()
     439[]
     440
     441Create a new article, with categories, via the form, but use commit=False.
     442The m2m data won't be saved until save_m2m() is invoked on the form.
     443>>> class ArticleForm(ModelForm):
     444...     class Meta:
     445...         model = Article
     446>>> f = ArticleForm(Article(), {'headline': u'The walrus was Paul', 'slug': 'walrus-was-paul', 'pub_date': u'1967-11-01',
     447...     'writer': u'1', 'article': u'Test.', 'categories': [u'1', u'2']})
     448>>> new_art = f.save(commit=False)
     449
     450# Manually save the instance
     451>>> new_art.save()
     452>>> new_art.id
     4534
     454
     455# The instance doesn't have m2m data yet
     456>>> new_art = Article.objects.get(id=4)
     457>>> new_art.categories.all()
     458[]
     459
     460# Save the m2m data on the form
     461>>> f.save_m2m()
     462>>> new_art.categories.order_by('name')
     463[<Category: Entertainment>, <Category: It's a test>]
     464
     465Here, we define a custom ModelForm. Because it happens to have the same fields as
     466the Category model, we can just call the form's save() to apply its changes to an
     467existing Category instance.
     468>>> class ShortCategory(ModelForm):
     469...     name = CharField(max_length=5)
     470...     slug = CharField(max_length=5)
     471...     url = CharField(max_length=3)
     472>>> cat = Category.objects.get(name='Third test')
     473>>> cat
     474<Category: Third test>
     475>>> cat.id
     4763
     477>>> form = ShortCategory(cat, {'name': 'Third', 'slug': 'third', 'url': '3rd'})
     478>>> form.save()
     479<Category: Third>
     480>>> Category.objects.get(id=3)
     481<Category: Third>
     482
     483Here, we demonstrate that choices for a ForeignKey ChoiceField are determined
     484at runtime, based on the data in the database when the form is displayed, not
     485the data in the database when the form is instantiated.
     486>>> class ArticleForm(ModelForm):
     487...     class Meta:
     488...         model = Article
     489>>> f = ArticleForm(Article(), auto_id=False)
     490>>> print f.as_ul()
     491<li>Headline: <input type="text" name="headline" maxlength="50" /></li>
     492<li>Slug: <input type="text" name="slug" maxlength="50" /></li>
     493<li>Pub date: <input type="text" name="pub_date" /></li>
     494<li>Writer: <select name="writer">
     495<option value="" selected="selected">---------</option>
     496<option value="1">Mike Royko</option>
     497<option value="2">Bob Woodward</option>
     498</select></li>
     499<li>Article: <textarea rows="10" cols="40" name="article"></textarea></li>
     500<li>Status: <select name="status">
     501<option value="" selected="selected">---------</option>
     502<option value="1">Draft</option>
     503<option value="2">Pending</option>
     504<option value="3">Live</option>
     505</select></li>
     506<li>Categories: <select multiple="multiple" name="categories">
     507<option value="1">Entertainment</option>
     508<option value="2">It&#39;s a test</option>
     509<option value="3">Third</option>
     510</select>  Hold down "Control", or "Command" on a Mac, to select more than one.</li>
     511>>> Category.objects.create(name='Fourth', url='4th')
     512<Category: Fourth>
     513>>> Writer.objects.create(name='Carl Bernstein')
     514<Writer: Carl Bernstein>
     515>>> print f.as_ul()
     516<li>Headline: <input type="text" name="headline" maxlength="50" /></li>
     517<li>Slug: <input type="text" name="slug" maxlength="50" /></li>
     518<li>Pub date: <input type="text" name="pub_date" /></li>
     519<li>Writer: <select name="writer">
     520<option value="" selected="selected">---------</option>
     521<option value="1">Mike Royko</option>
     522<option value="2">Bob Woodward</option>
     523<option value="3">Carl Bernstein</option>
     524</select></li>
     525<li>Article: <textarea rows="10" cols="40" name="article"></textarea></li>
     526<li>Status: <select name="status">
     527<option value="" selected="selected">---------</option>
     528<option value="1">Draft</option>
     529<option value="2">Pending</option>
     530<option value="3">Live</option>
     531</select></li>
     532<li>Categories: <select multiple="multiple" name="categories">
     533<option value="1">Entertainment</option>
     534<option value="2">It&#39;s a test</option>
     535<option value="3">Third</option>
     536<option value="4">Fourth</option>
     537</select>  Hold down "Control", or "Command" on a Mac, to select more than one.</li>
     538
     539# ModelChoiceField ############################################################
     540
     541>>> from django.newforms import ModelChoiceField, ModelMultipleChoiceField
     542
     543>>> f = ModelChoiceField(Category.objects.all())
     544>>> list(f.choices)
     545[(u'', u'---------'), (1, u'Entertainment'), (2, u"It's a test"), (3, u'Third'), (4, u'Fourth')]
     546>>> f.clean('')
     547Traceback (most recent call last):
     548...
     549ValidationError: [u'This field is required.']
     550>>> f.clean(None)
     551Traceback (most recent call last):
     552...
     553ValidationError: [u'This field is required.']
     554>>> f.clean(0)
     555Traceback (most recent call last):
     556...
     557ValidationError: [u'Select a valid choice. That choice is not one of the available choices.']
     558>>> f.clean(3)
     559<Category: Third>
     560>>> f.clean(2)
     561<Category: It's a test>
     562
     563# Add a Category object *after* the ModelChoiceField has already been
     564# instantiated. This proves clean() checks the database during clean() rather
     565# than caching it at time of instantiation.
     566>>> Category.objects.create(name='Fifth', url='5th')
     567<Category: Fifth>
     568>>> f.clean(5)
     569<Category: Fifth>
     570
     571# Delete a Category object *after* the ModelChoiceField has already been
     572# instantiated. This proves clean() checks the database during clean() rather
     573# than caching it at time of instantiation.
     574>>> Category.objects.get(url='5th').delete()
     575>>> f.clean(5)
     576Traceback (most recent call last):
     577...
     578ValidationError: [u'Select a valid choice. That choice is not one of the available choices.']
     579
     580>>> f = ModelChoiceField(Category.objects.filter(pk=1), required=False)
     581>>> print f.clean('')
     582None
     583>>> f.clean('')
     584>>> f.clean('1')
     585<Category: Entertainment>
     586>>> f.clean('100')
     587Traceback (most recent call last):
     588...
     589ValidationError: [u'Select a valid choice. That choice is not one of the available choices.']
     590
     591# queryset can be changed after the field is created.
     592>>> f.queryset = Category.objects.exclude(name='Fourth')
     593>>> list(f.choices)
     594[(u'', u'---------'), (1, u'Entertainment'), (2, u"It's a test"), (3, u'Third')]
     595>>> f.clean(3)
     596<Category: Third>
     597>>> f.clean(4)
     598Traceback (most recent call last):
     599...
     600ValidationError: [u'Select a valid choice. That choice is not one of the available choices.']
     601
     602
     603# ModelMultipleChoiceField ####################################################
     604
     605>>> f = ModelMultipleChoiceField(Category.objects.all())
     606>>> list(f.choices)
     607[(1, u'Entertainment'), (2, u"It's a test"), (3, u'Third'), (4, u'Fourth')]
     608>>> f.clean(None)
     609Traceback (most recent call last):
     610...
     611ValidationError: [u'This field is required.']
     612>>> f.clean([])
     613Traceback (most recent call last):
     614...
     615ValidationError: [u'This field is required.']
     616>>> f.clean([1])
     617[<Category: Entertainment>]
     618>>> f.clean([2])
     619[<Category: It's a test>]
     620>>> f.clean(['1'])
     621[<Category: Entertainment>]
     622>>> f.clean(['1', '2'])
     623[<Category: Entertainment>, <Category: It's a test>]
     624>>> f.clean([1, '2'])
     625[<Category: Entertainment>, <Category: It's a test>]
     626>>> f.clean((1, '2'))
     627[<Category: Entertainment>, <Category: It's a test>]
     628>>> f.clean(['100'])
     629Traceback (most recent call last):
     630...
     631ValidationError: [u'Select a valid choice. 100 is not one of the available choices.']
     632>>> f.clean('hello')
     633Traceback (most recent call last):
     634...
     635ValidationError: [u'Enter a list of values.']
     636
     637# Add a Category object *after* the ModelMultipleChoiceField has already been
     638# instantiated. This proves clean() checks the database during clean() rather
     639# than caching it at time of instantiation.
     640>>> Category.objects.create(id=6, name='Sixth', url='6th')
     641<Category: Sixth>
     642>>> f.clean([6])
     643[<Category: Sixth>]
     644
     645# Delete a Category object *after* the ModelMultipleChoiceField has already been
     646# instantiated. This proves clean() checks the database during clean() rather
     647# than caching it at time of instantiation.
     648>>> Category.objects.get(url='6th').delete()
     649>>> f.clean([6])
     650Traceback (most recent call last):
     651...
     652ValidationError: [u'Select a valid choice. 6 is not one of the available choices.']
     653
     654>>> f = ModelMultipleChoiceField(Category.objects.all(), required=False)
     655>>> f.clean([])
     656[]
     657>>> f.clean(())
     658[]
     659>>> f.clean(['10'])
     660Traceback (most recent call last):
     661...
     662ValidationError: [u'Select a valid choice. 10 is not one of the available choices.']
     663>>> f.clean(['3', '10'])
     664Traceback (most recent call last):
     665...
     666ValidationError: [u'Select a valid choice. 10 is not one of the available choices.']
     667>>> f.clean(['1', '10'])
     668Traceback (most recent call last):
     669...
     670ValidationError: [u'Select a valid choice. 10 is not one of the available choices.']
     671
     672# queryset can be changed after the field is created.
     673>>> f.queryset = Category.objects.exclude(name='Fourth')
     674>>> list(f.choices)
     675[(1, u'Entertainment'), (2, u"It's a test"), (3, u'Third')]
     676>>> f.clean([3])
     677[<Category: Third>]
     678>>> f.clean([4])
     679Traceback (most recent call last):
     680...
     681ValidationError: [u'Select a valid choice. 4 is not one of the available choices.']
     682>>> f.clean(['3', '4'])
     683Traceback (most recent call last):
     684...
     685ValidationError: [u'Select a valid choice. 4 is not one of the available choices.']
     686
     687
     688# PhoneNumberField ############################################################
     689
     690>>> class PhoneNumberForm(ModelForm):
     691...     class Meta:
     692...         model = PhoneNumber
     693>>> f = PhoneNumberForm(PhoneNumber(), {'phone': '(312) 555-1212', 'description': 'Assistance'})
     694>>> f.is_valid()
     695True
     696>>> f.cleaned_data
     697{'phone': u'312-555-1212', 'description': u'Assistance'}
     698"""}
Back to Top