# HG changeset patch
# Parent 6348119c628a728095e696dd606541752c32f7c8
diff --git a/django/forms/models.py b/django/forms/models.py
|
a
|
b
|
|
| 151 | 151 | data[f.name] = f.value_from_object(instance) |
| 152 | 152 | return data |
| 153 | 153 | |
| 154 | | def fields_for_model(model, fields=None, exclude=None, widgets=None, formfield_callback=None): |
| | 154 | def fields_for_model(model, fields=None, exclude=None, widgets=None, fields_kwargs=None, formfield_callback=None): |
| 155 | 155 | """ |
| 156 | 156 | Returns a ``SortedDict`` containing form fields for the given model. |
| 157 | 157 | |
| … |
… |
|
| 172 | 172 | continue |
| 173 | 173 | if exclude and f.name in exclude: |
| 174 | 174 | continue |
| 175 | | if widgets and f.name in widgets: |
| 176 | | kwargs = {'widget': widgets[f.name]} |
| | 175 | if fields_kwargs and f.name in fields_kwargs: |
| | 176 | kwargs = fields_kwargs[f.name].copy() |
| 177 | 177 | else: |
| 178 | 178 | kwargs = {} |
| | 179 | if widgets and f.name in widgets: |
| | 180 | kwargs['widget'] = widgets[f.name] |
| 179 | 181 | |
| 180 | 182 | if formfield_callback is None: |
| 181 | 183 | formfield = f.formfield(**kwargs) |
| … |
… |
|
| 202 | 204 | self.fields = getattr(options, 'fields', None) |
| 203 | 205 | self.exclude = getattr(options, 'exclude', None) |
| 204 | 206 | self.widgets = getattr(options, 'widgets', None) |
| | 207 | self.fields_kwargs = getattr(options, 'fields_kwargs', None) |
| 205 | 208 | |
| 206 | 209 | |
| 207 | 210 | class ModelFormMetaclass(type): |
| … |
… |
|
| 223 | 226 | opts = new_class._meta = ModelFormOptions(getattr(new_class, 'Meta', None)) |
| 224 | 227 | if opts.model: |
| 225 | 228 | # If a model is defined, extract form fields from it. |
| 226 | | fields = fields_for_model(opts.model, opts.fields, |
| 227 | | opts.exclude, opts.widgets, formfield_callback) |
| | 229 | fields = fields_for_model(opts.model, opts.fields, opts.exclude, |
| | 230 | opts.widgets, opts.fields_kwargs, formfield_callback) |
| 228 | 231 | # make sure opts.fields doesn't specify an invalid field |
| 229 | 232 | none_model_fields = [k for k, v in fields.iteritems() if not v] |
| 230 | 233 | missing_fields = set(none_model_fields) - \ |
diff --git a/tests/modeltests/model_forms/models.py b/tests/modeltests/model_forms/models.py
|
a
|
b
|
|
| 322 | 322 | >>> CategoryForm.base_fields.keys() |
| 323 | 323 | ['name'] |
| 324 | 324 | |
| | 325 | Using 'fields_kwargs' |
| | 326 | |
| | 327 | >>> class CategoryForm(ModelForm): |
| | 328 | ... |
| | 329 | ... class Meta: |
| | 330 | ... model = Category |
| | 331 | ... fields = ['name', 'url', 'slug'] |
| | 332 | ... fields_kwargs = { |
| | 333 | ... 'name': {'label': 'Category name', 'widget': forms.Textarea(attrs={'rows': '5', 'cols': '20'})}, |
| | 334 | ... 'url': {'max_length': 30}, |
| | 335 | ... 'slug': {'max_length': 10, 'widget': forms.TextInput(attrs={'class': 'slug'})}, |
| | 336 | ... } |
| | 337 | |
| | 338 | >>> print CategoryForm() |
| | 339 | <tr><th><label for="id_name">Category name:</label></th><td><textarea id="id_name" rows="5" cols="20" name="name"></textarea></td></tr> |
| | 340 | <tr><th><label for="id_url">The URL:</label></th><td><input id="id_url" type="text" name="url" maxlength="30" /></td></tr> |
| | 341 | <tr><th><label for="id_slug">Slug:</label></th><td><input id="id_slug" type="text" class="slug" name="slug" maxlength="10" /></td></tr> |
| | 342 | |
| 325 | 343 | Using 'widgets' |
| 326 | 344 | |
| 327 | 345 | >>> class CategoryForm(ModelForm): |
| … |
… |
|
| 343 | 361 | >>> str(CategoryForm()['slug']) |
| 344 | 362 | '<input id="id_slug" type="text" name="slug" maxlength="20" />' |
| 345 | 363 | |
| | 364 | Using 'fields_kwargs' and 'widgets' at once - 'widgets' have higher priority |
| | 365 | |
| | 366 | >>> class CategoryForm(ModelForm): |
| | 367 | ... |
| | 368 | ... class Meta: |
| | 369 | ... model = Category |
| | 370 | ... fields = ['name', 'url', 'slug'] |
| | 371 | ... widgets = { |
| | 372 | ... 'name': forms.Textarea, |
| | 373 | ... 'url': forms.TextInput(attrs={'class': 'url'}) |
| | 374 | ... } |
| | 375 | ... fields_kwargs = { |
| | 376 | ... 'name': {'label': 'Category name', 'widget': forms.Textarea(attrs={'rows': '5', 'cols': '20'})}, |
| | 377 | ... 'url': {'max_length': 30}, |
| | 378 | ... 'slug': {'max_length': 10, 'widget': forms.TextInput(attrs={'class': 'slug'})}, |
| | 379 | ... } |
| | 380 | |
| | 381 | >>> str(CategoryForm()['name']) |
| | 382 | '<textarea id="id_name" rows="10" cols="40" name="name"></textarea>' |
| | 383 | |
| | 384 | >>> str(CategoryForm()['url']) |
| | 385 | '<input id="id_url" type="text" class="url" name="url" maxlength="30" />' |
| | 386 | |
| | 387 | >>> str(CategoryForm()['slug']) |
| | 388 | '<input id="id_slug" type="text" class="slug" name="slug" maxlength="10" />' |
| | 389 | |
| 346 | 390 | Don't allow more than one 'model' definition in the inheritance hierarchy. |
| 347 | 391 | Technically, it would generate a valid form, but the fact that the resulting |
| 348 | 392 | save method won't deal with multiple objects is likely to trip up people not |