Django

Code

Ticket #6042: modelforms.diff

File modelforms.diff, 81.2 kB (added by jkocherhans, 9 months ago)

Now with updated docs and less stupidity thanks to Malcolm.

  • a/django/newforms/models.py

    old new  
    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) 
     
    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 
     
    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 
  • /dev/null

    old new  
     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. 
  • /dev/null

    old new  
     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 
  • a/docs/newforms.txt

    old new  
    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``        &nb