Commit 93e79b45 authored by Nick Sandford's avatar Nick Sandford Committed by Claude Paroz
Browse files

Fixed #17416 -- Added widgets argument to inlineformset_factory and modelformset_factory

parent 71c85395
Loading
Loading
Loading
Loading
+7 −5
Original line number Diff line number Diff line
@@ -682,14 +682,15 @@ class BaseModelFormSet(BaseFormSet):
        super(BaseModelFormSet, self).add_fields(form, index)

def modelformset_factory(model, form=ModelForm, formfield_callback=None,
                         formset=BaseModelFormSet,
                         extra=1, can_delete=False, can_order=False,
                         max_num=None, fields=None, exclude=None):
                         formset=BaseModelFormSet, extra=1, can_delete=False,
                         can_order=False, max_num=None, fields=None,
                         exclude=None, widgets=None):
    """
    Returns a FormSet class for the given Django model class.
    """
    form = modelform_factory(model, form=form, fields=fields, exclude=exclude,
                             formfield_callback=formfield_callback)
                             formfield_callback=formfield_callback,
                             widgets=widgets)
    FormSet = formset_factory(form, formset, extra=extra, max_num=max_num,
                              can_order=can_order, can_delete=can_delete)
    FormSet.model = model
@@ -827,7 +828,7 @@ def inlineformset_factory(parent_model, model, form=ModelForm,
                          formset=BaseInlineFormSet, fk_name=None,
                          fields=None, exclude=None,
                          extra=3, can_order=False, can_delete=True, max_num=None,
                          formfield_callback=None):
                          formfield_callback=None, widgets=None):
    """
    Returns an ``InlineFormSet`` for the given kwargs.

@@ -848,6 +849,7 @@ def inlineformset_factory(parent_model, model, form=ModelForm,
        'fields': fields,
        'exclude': exclude,
        'max_num': max_num,
        'widgets': widgets,
    }
    FormSet = modelformset_factory(model, **kwargs)
    FormSet.fk = fk
+12 −4
Original line number Diff line number Diff line
@@ -25,12 +25,12 @@ Model Form Functions

    See :ref:`modelforms-factory` for example usage.

.. function:: modelformset_factory(model, form=ModelForm, formfield_callback=None, formset=BaseModelFormSet, extra=1, can_delete=False, can_order=False, max_num=None, fields=None, exclude=None)
.. function:: modelformset_factory(model, form=ModelForm, formfield_callback=None, formset=BaseModelFormSet, extra=1, can_delete=False, can_order=False, max_num=None, fields=None, exclude=None, widgets=None)

    Returns a ``FormSet`` class for the given ``model`` class.

    Arguments ``model``, ``form``, ``fields``, ``exclude``, and
    ``formfield_callback`` are all passed through to
    Arguments ``model``, ``form``, ``fields``, ``exclude``,
    ``formfield_callback`` and ``widgets`` are all passed through to
    :func:`~django.forms.models.modelform_factory`.

    Arguments ``formset``, ``extra``, ``max_num``, ``can_order``, and
@@ -39,7 +39,11 @@ Model Form Functions

    See :ref:`model-formsets` for example usage.

.. function:: inlineformset_factory(parent_model, model, form=ModelForm, formset=BaseInlineFormSet, fk_name=None, fields=None, exclude=None, extra=3, can_order=False, can_delete=True, max_num=None, formfield_callback=None)
    .. versionchanged:: 1.6

    The widgets parameter was added.

.. function:: inlineformset_factory(parent_model, model, form=ModelForm, formset=BaseInlineFormSet, fk_name=None, fields=None, exclude=None, extra=3, can_order=False, can_delete=True, max_num=None, formfield_callback=None, widgets=None)

    Returns an ``InlineFormSet`` using :func:`modelformset_factory` with
    defaults of ``formset=BaseInlineFormSet``, ``can_delete=True``, and
@@ -49,3 +53,7 @@ Model Form Functions
    the ``parent_model``, you must specify a ``fk_name``.

    See :ref:`inline-formsets` for example usage.

    .. versionchanged:: 1.6

    The widgets parameter was added.
+23 −0
Original line number Diff line number Diff line
@@ -650,6 +650,19 @@ exclude::

    >>> AuthorFormSet = modelformset_factory(Author, exclude=('birth_date',))

Specifying widgets to use in the form with ``widgets``
------------------------------------------------------

.. versionadded:: 1.6

Using the ``widgets`` parameter, you can specify a dictionary of values to
customize the ``ModelForm``'s widget class for a particular field. This
works the same way as the ``widgets`` dictionary on the inner ``Meta``
class of a ``ModelForm`` works::

    >>> AuthorFormSet = modelformset_factory(
    ...     Author, widgets={'name': Textarea(attrs={'cols': 80, 'rows': 20})

Providing initial values
------------------------

@@ -930,3 +943,13 @@ of a model. Here's how you can do that::
        })

Notice how we pass ``instance`` in both the ``POST`` and ``GET`` cases.

Specifying widgets to use in the inline form
--------------------------------------------

.. versionadded:: 1.6

``inlineformset_factory`` uses ``modelformset_factory`` and passes most
of its arguments to ``modelformset_factory``. This means you can use
the ``widgets`` parameter in much the same way as passing it to
``modelformset_factory``. See `Specifying widgets to use in the form with widgets`_ above.
+24 −0
Original line number Diff line number Diff line
@@ -1190,3 +1190,27 @@ class ModelFormsetTest(TestCase):
        self.assertFalse(formset.is_valid())
        self.assertEqual(formset._non_form_errors,
            ['Please correct the duplicate data for subtitle which must be unique for the month in posted.'])


class TestModelFormsetWidgets(TestCase):
    def test_modelformset_factory_widgets(self):
        widgets = {
            'name': forms.TextInput(attrs={'class': 'poet'})
        }
        PoetFormSet = modelformset_factory(Poet, widgets=widgets)
        form = PoetFormSet.form()
        self.assertHTMLEqual(
            "%s" % form['name'],
            '<input id="id_name" maxlength="100" type="text" class="poet" name="name" />'
        )

    def test_inlineformset_factory_widgets(self):
        widgets = {
            'title': forms.TextInput(attrs={'class': 'book'})
        }
        BookFormSet = inlineformset_factory(Author, Book, widgets=widgets)
        form = BookFormSet.form()
        self.assertHTMLEqual(
            "%s" % form['title'],
            '<input class="book" id="id_title" maxlength="100" name="title" type="text" />'
        )