Commit a097ee32 authored by Simon Charette's avatar Simon Charette
Browse files

Fixed #17683 -- Make sure `BaseModelFormSet` respects defined widgets.

parent ec469ade
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
@@ -678,7 +678,11 @@ class BaseModelFormSet(BaseFormSet):
            else:
                qs = self.model._default_manager.get_query_set()
            qs = qs.using(form.instance._state.db)
            form.fields[self._pk_field.name] = ModelChoiceField(qs, initial=pk_value, required=False, widget=HiddenInput)
            if form._meta.widgets:
                widget = form._meta.widgets.get(self._pk_field.name, HiddenInput)
            else:
                widget = HiddenInput
            form.fields[self._pk_field.name] = ModelChoiceField(qs, initial=pk_value, required=False, widget=widget)
        super(BaseModelFormSet, self).add_fields(form, index)

def modelformset_factory(model, form=ModelForm, formfield_callback=None,
+11 −6
Original line number Diff line number Diff line
@@ -261,14 +261,17 @@ class FormsetTests(TestCase):
            formset.save()


class CustomWidget(forms.CharField):
class CustomWidget(forms.widgets.TextInput):
    pass


class UserSiteForm(forms.ModelForm):
    class Meta:
        model = UserSite
        widgets = {'data': CustomWidget}
        widgets = {
            'id': CustomWidget,
            'data': CustomWidget,
        }


class Callback(object):
@@ -283,24 +286,27 @@ class Callback(object):

class FormfieldCallbackTests(TestCase):
    """
    Regression for #13095: Using base forms with widgets
    defined in Meta should not raise errors.
    Regression for #13095 and #17683: Using base forms with widgets
    defined in Meta should not raise errors and BaseModelForm should respect
    the specified pk widget.
    """

    def test_inlineformset_factory_default(self):
        Formset = inlineformset_factory(User, UserSite, form=UserSiteForm)
        form = Formset().forms[0]
        self.assertTrue(isinstance(form['id'].field.widget, CustomWidget))
        self.assertTrue(isinstance(form['data'].field.widget, CustomWidget))

    def test_modelformset_factory_default(self):
        Formset = modelformset_factory(UserSite, form=UserSiteForm)
        form = Formset().forms[0]
        self.assertTrue(isinstance(form['id'].field.widget, CustomWidget))
        self.assertTrue(isinstance(form['data'].field.widget, CustomWidget))

    def assertCallbackCalled(self, callback):
        id_field, user_field, data_field = UserSite._meta.fields
        expected_log = [
            (id_field, {}),
            (id_field, {'widget': CustomWidget}),
            (user_field, {}),
            (data_field, {'widget': CustomWidget}),
        ]
@@ -318,7 +324,6 @@ class FormfieldCallbackTests(TestCase):
                             formfield_callback=callback)
        self.assertCallbackCalled(callback)


class BaseCustomDeleteFormSet(BaseFormSet):
    """
    A formset mix-in that lets a form decide if it's to be deleted.