Ticket #9223: 9223.4.diff

File 9223.4.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'
     
    159159            data[f.name] = f.value_from_object(instance)
    160160    return data
    161161
    162 def fields_for_model(model, fields=None, exclude=None, formfield_callback=lambda f: f.formfield()):
     162def fields_for_model(model, fields=None, exclude=None, widgets=None, formfield_callback=lambda f, **kwargs: f.formfield(**kwargs)):
    163163    """
    164164    Returns a ``SortedDict`` containing form fields for the given model.
    165165
     
    179179            continue
    180180        if exclude and f.name in exclude:
    181181            continue
    182         formfield = formfield_callback(f)
     182        if widgets and f.name in widgets:
     183            kwargs = {'widget': widgets[f.name]}
     184        else:
     185            kwargs = {}
     186        formfield = formfield_callback(f, **kwargs)
    183187        if formfield:
    184188            field_list.append((f.name, formfield))
    185189    field_dict = SortedDict(field_list)
     
    192196        self.model = getattr(options, 'model', None)
    193197        self.fields = getattr(options, 'fields', None)
    194198        self.exclude = getattr(options, 'exclude', None)
     199        self.widgets = getattr(options, 'widgets', None)
    195200
    196201
    197202class ModelFormMetaclass(type):
    198203    def __new__(cls, name, bases, attrs):
    199204        formfield_callback = attrs.pop('formfield_callback',
    200                 lambda f: f.formfield())
     205                lambda f, **kwargs: f.formfield(**kwargs))
    201206        try:
    202207            parents = [b for b in bases if issubclass(b, ModelForm)]
    203208        except NameError:
     
    215220        if opts.model:
    216221            # If a model is defined, extract form fields from it.
    217222            fields = fields_for_model(opts.model, opts.fields,
    218                                       opts.exclude, formfield_callback)
     223                                      opts.exclude, opts.widgets, formfield_callback)
    219224            # Override default model fields with any custom declared ones
    220225            # (plus, include all the other declared fields).
    221226            fields.update(declared_fields)
  • docs/topics/forms/modelforms.txt

    === modified file 'docs/topics/forms/modelforms.txt'
     
    350350
    351351.. _section on saving forms: `The save() method`_
    352352
    353 Overriding the default field types
    354 ----------------------------------
     353Overriding the default field types or widgets
     354---------------------------------------------
    355355
    356356The default field types, as described in the `Field types`_ table above, are
    357357sensible defaults. If you have a ``DateField`` in your model, chances are you'd
    358358want that to be represented as a ``DateField`` in your form. But
    359 ``ModelForm`` gives you the flexibility of changing the form field type
    360 for a given model field. You do this by declaratively specifying fields like
    361 you would in a regular ``Form``. Declared fields will override the default
    362 ones generated by using the ``model`` attribute.
     359``ModelForm`` gives you the flexibility of changing the form field type and
     360widget for a given model field.
     361
     362To specify a custom widget for a field use the ``widgets`` attribute og the
     363inner ``Meta`` class. For example if you want the default textarea for the TextField
     364to have custom ``cols`` and ``rows`` attributes you can override its widget:
     365
     366>>> class ArticleForm(ModelForm)
     367...     class Meta:
     368...         model = ArticleForm
     369...         fields = ['title', 'text']
     370...         widgets = {
     371...             'text': Textarea(attrs={'cols': 80, 'rows': 20})
     372...         }
     373
     374``Widgets`` dictionary accepts both widget instances (i.e. ``Textarea(...)``) as well
     375as classes (i.e. ``Textarea``).
     376
     377If you want to further customize the field including its type, label etc., you do this
     378by declaratively specifying fields like you would in a regular ``Form``. Declared
     379fields will override the default ones generated by using the ``model`` attribute.
    363380
    364381For example, if you wanted to use ``MyDateFormField`` for the ``pub_date``
    365382field, you could do the following::
     
    370387    ...     class Meta:
    371388    ...         model = Article
    372389
    373 If you want to override a field's default widget, then specify the ``widget``
     390If you want to override a field's default label, then specify the ``label``
    374391parameter when declaring the form field::
    375392
    376393   >>> class ArticleForm(ModelForm):
    377    ...     pub_date = DateField(widget=MyDateWidget())
     394   ...     pub_date = DateField(label='Publication date')
    378395   ...
    379396   ...     class Meta:
    380397   ...         model = Article
  • tests/modeltests/model_forms/models.py

    === modified file 'tests/modeltests/model_forms/models.py'
     
    287287>>> CategoryForm.base_fields.keys()
    288288['name']
    289289
     290Using 'widgets'
     291
     292>>> class CategoryForm(ModelForm):
     293...
     294...     class Meta:
     295...         model = Category
     296...         fields = ['name', 'url', 'slug']
     297...         widgets = {
     298...             'name': forms.Textarea,
     299...             'url': forms.TextInput(attrs={'class': 'url'})
     300...         }
     301
     302>>> str(CategoryForm()['name'])
     303'<textarea id="id_name" rows="10" cols="40" name="name"></textarea>'
     304
     305>>> str(CategoryForm()['url'])
     306'<input id="id_url" type="text" class="url" name="url" maxlength="40" />'
     307
     308>>> str(CategoryForm()['slug'])
     309'<input id="id_slug" type="text" name="slug" maxlength="20" />'
     310
    290311Don't allow more than one 'model' definition in the inheritance hierarchy.
    291312Technically, it would generate a valid form, but the fact that the resulting
    292313save method won't deal with multiple objects is likely to trip up people not
Back to Top