# HG changeset patch
# Parent 6348119c628a728095e696dd606541752c32f7c8

diff --git a/django/forms/models.py b/django/forms/models.py
--- a/django/forms/models.py
+++ b/django/forms/models.py
@@ -151,7 +151,7 @@
             data[f.name] = f.value_from_object(instance)
     return data
 
-def fields_for_model(model, fields=None, exclude=None, widgets=None, formfield_callback=None):
+def fields_for_model(model, fields=None, exclude=None, widgets=None, fields_kwargs=None, formfield_callback=None):
     """
     Returns a ``SortedDict`` containing form fields for the given model.
 
@@ -172,10 +172,12 @@
             continue
         if exclude and f.name in exclude:
             continue
-        if widgets and f.name in widgets:
-            kwargs = {'widget': widgets[f.name]}
+        if fields_kwargs and f.name in fields_kwargs:
+            kwargs = fields_kwargs[f.name].copy()
         else:
             kwargs = {}
+        if widgets and f.name in widgets:
+            kwargs['widget'] = widgets[f.name]
 
         if formfield_callback is None:
             formfield = f.formfield(**kwargs)
@@ -202,6 +204,7 @@
         self.fields = getattr(options, 'fields', None)
         self.exclude = getattr(options, 'exclude', None)
         self.widgets = getattr(options, 'widgets', None)
+        self.fields_kwargs = getattr(options, 'fields_kwargs', None)
 
 
 class ModelFormMetaclass(type):
@@ -223,8 +226,8 @@
         opts = new_class._meta = ModelFormOptions(getattr(new_class, 'Meta', None))
         if opts.model:
             # If a model is defined, extract form fields from it.
-            fields = fields_for_model(opts.model, opts.fields,
-                                      opts.exclude, opts.widgets, formfield_callback)
+            fields = fields_for_model(opts.model, opts.fields, opts.exclude,
+                opts.widgets, opts.fields_kwargs, formfield_callback)
             # make sure opts.fields doesn't specify an invalid field
             none_model_fields = [k for k, v in fields.iteritems() if not v]
             missing_fields = set(none_model_fields) - \
diff --git a/tests/modeltests/model_forms/models.py b/tests/modeltests/model_forms/models.py
--- a/tests/modeltests/model_forms/models.py
+++ b/tests/modeltests/model_forms/models.py
@@ -322,6 +322,24 @@
 >>> CategoryForm.base_fields.keys()
 ['name']
 
+Using 'fields_kwargs'
+
+>>> class CategoryForm(ModelForm):
+...
+...     class Meta:
+...         model = Category
+...         fields = ['name', 'url', 'slug']
+...         fields_kwargs = {
+...             'name': {'label': 'Category name', 'widget': forms.Textarea(attrs={'rows': '5', 'cols': '20'})},
+...             'url': {'max_length': 30},
+...             'slug': {'max_length': 10, 'widget': forms.TextInput(attrs={'class': 'slug'})},
+...         }
+
+>>> print CategoryForm()
+<tr><th><label for="id_name">Category name:</label></th><td><textarea id="id_name" rows="5" cols="20" name="name"></textarea></td></tr>
+<tr><th><label for="id_url">The URL:</label></th><td><input id="id_url" type="text" name="url" maxlength="30" /></td></tr>
+<tr><th><label for="id_slug">Slug:</label></th><td><input id="id_slug" type="text" class="slug" name="slug" maxlength="10" /></td></tr>
+
 Using 'widgets'
 
 >>> class CategoryForm(ModelForm):
@@ -343,6 +361,32 @@
 >>> str(CategoryForm()['slug'])
 '<input id="id_slug" type="text" name="slug" maxlength="20" />'
 
+Using 'fields_kwargs' and 'widgets' at once - 'widgets' have higher priority
+
+>>> class CategoryForm(ModelForm):
+...
+...     class Meta:
+...         model = Category
+...         fields = ['name', 'url', 'slug']
+...         widgets = {
+...             'name': forms.Textarea,
+...             'url': forms.TextInput(attrs={'class': 'url'})
+...         }
+...         fields_kwargs = {
+...             'name': {'label': 'Category name', 'widget': forms.Textarea(attrs={'rows': '5', 'cols': '20'})},
+...             'url': {'max_length': 30},
+...             'slug': {'max_length': 10, 'widget': forms.TextInput(attrs={'class': 'slug'})},
+...         }
+
+>>> str(CategoryForm()['name'])
+'<textarea id="id_name" rows="10" cols="40" name="name"></textarea>'
+
+>>> str(CategoryForm()['url'])
+'<input id="id_url" type="text" class="url" name="url" maxlength="30" />'
+
+>>> str(CategoryForm()['slug'])
+'<input id="id_slug" type="text" class="slug" name="slug" maxlength="10" />'
+
 Don't allow more than one 'model' definition in the inheritance hierarchy.
 Technically, it would generate a valid form, but the fact that the resulting
 save method won't deal with multiple objects is likely to trip up people not
