Ticket #9223: 9223.3.diff

File 9223.3.diff, 5.6 KB (added by Ivan Sagalaev, 15 years ago)

Patch updated to current trunk

  • django/forms/models.py

    === modified file 'django/forms/models.py'
     
    138138            data[f.name] = f.value_from_object(instance)
    139139    return data
    140140
    141 def fields_for_model(model, fields=None, exclude=None, formfield_callback=lambda f: f.formfield()):
     141def fields_for_model(model, fields=None, exclude=None, widgets=None, formfield_callback=lambda f, **kwargs: f.formfield(**kwargs)):
    142142    """
    143143    Returns a ``SortedDict`` containing form fields for the given model.
    144144
     
    159159            continue
    160160        if exclude and f.name in exclude:
    161161            continue
    162         formfield = formfield_callback(f)
     162        if widgets and f.name in widgets:
     163            kwargs = {'widget': widgets[f.name]}
     164        else:
     165            kwargs = {}
     166        formfield = formfield_callback(f, **kwargs)
    163167        if formfield:
    164168            field_list.append((f.name, formfield))
    165169    return SortedDict(field_list)
     
    169173        self.model = getattr(options, 'model', None)
    170174        self.fields = getattr(options, 'fields', None)
    171175        self.exclude = getattr(options, 'exclude', None)
     176        self.widgets = getattr(options, 'widgets', None)
    172177
    173178
    174179class ModelFormMetaclass(type):
    175180    def __new__(cls, name, bases, attrs):
    176181        formfield_callback = attrs.pop('formfield_callback',
    177                 lambda f: f.formfield())
     182                lambda f, **kwargs: f.formfield(**kwargs))
    178183        try:
    179184            parents = [b for b in bases if issubclass(b, ModelForm)]
    180185        except NameError:
     
    192197        if opts.model:
    193198            # If a model is defined, extract form fields from it.
    194199            fields = fields_for_model(opts.model, opts.fields,
    195                                       opts.exclude, formfield_callback)
     200                                      opts.exclude, opts.widgets, formfield_callback)
    196201            # Override default model fields with any custom declared ones
    197202            # (plus, include all the other declared fields).
    198203            fields.update(declared_fields)
  • docs/topics/forms/modelforms.txt

    === modified file 'docs/topics/forms/modelforms.txt'
     
    307307
    308308.. _section on saving forms: `The save() method`_
    309309
    310 Overriding the default field types
    311 ----------------------------------
     310Overriding the default field types or widgets
     311---------------------------------------------
    312312
    313313The default field types, as described in the `Field types`_ table above, are
    314314sensible defaults. If you have a ``DateField`` in your model, chances are you'd
    315315want that to be represented as a ``DateField`` in your form. But
    316 ``ModelForm`` gives you the flexibility of changing the form field type
    317 for a given model field. You do this by declaratively specifying fields like
    318 you would in a regular ``Form``. Declared fields will override the default
    319 ones generated by using the ``model`` attribute.
     316``ModelForm`` gives you the flexibility of changing the form field type and
     317widget for a given model field.
     318
     319To specify a custom widget for a field use the ``widgets`` attribute og the
     320inner ``Meta`` class. For example if you want the default textarea for the TextField
     321to have custom ``cols`` and ``rows`` attributes you can override its widget:
     322
     323>>> class ArticleForm(ModelForm)
     324...     class Meta:
     325...         model = ArticleForm
     326...         fields = ['title', 'text']
     327...         widgets = {
     328...             'text': Textarea(attrs={'cols': 80, 'rows': 20})
     329...         }
     330
     331``Widgets`` dictionary accepts both widget instances (i.e. ``Textarea(...)``) as well
     332as classes (i.e. ``Textarea``).
     333
     334If you want to further customize the field including its type, label etc., you do this
     335by declaratively specifying fields like you would in a regular ``Form``. Declared
     336fields will override the default ones generated by using the ``model`` attribute.
    320337
    321338For example, if you wanted to use ``MyDateFormField`` for the ``pub_date``
    322339field, you could do the following::
     
    327344    ...     class Meta:
    328345    ...         model = Article
    329346
    330 If you want to override a field's default widget, then specify the ``widget``
     347If you want to override a field's default label, then specify the ``label``
    331348parameter when declaring the form field::
    332349
    333350   >>> class ArticleForm(ModelForm):
    334    ...     pub_date = DateField(widget=MyDateWidget())
     351   ...     pub_date = DateField(label='Publication date')
    335352   ...
    336353   ...     class Meta:
    337354   ...         model = Article
  • tests/modeltests/model_forms/models.py

    === modified file 'tests/modeltests/model_forms/models.py'
     
    275275>>> CategoryForm.base_fields.keys()
    276276['name']
    277277
     278Using 'widgets'
     279
     280>>> class CategoryForm(ModelForm):
     281...
     282...     class Meta:
     283...         model = Category
     284...         fields = ['name', 'url', 'slug']
     285...         widgets = {
     286...             'name': forms.Textarea,
     287...             'url': forms.TextInput(attrs={'class': 'url'})
     288...         }
     289
     290>>> str(CategoryForm()['name'])
     291'<textarea id="id_name" rows="10" cols="40" name="name"></textarea>'
     292
     293>>> str(CategoryForm()['url'])
     294'<input id="id_url" type="text" class="url" name="url" maxlength="40" />'
     295
     296>>> str(CategoryForm()['slug'])
     297'<input id="id_slug" type="text" name="slug" maxlength="20" />'
     298
    278299Don't allow more than one 'model' definition in the inheritance hierarchy.
    279300Technically, it would generate a valid form, but the fact that the resulting
    280301save method won't deal with multiple objects is likely to trip up people not
Back to Top