Why does onchange fail on modelForm?

I have two forms

class FirstForm(forms.Form):
    pick = forms.ChoiceField(
        widget=forms.Select(attrs={"onchange": "this.form.submit();"})
    )

class SecondForm(forms.ModelForm):
    class Meta:
        fields = "__all__"
        widgets = {
            "pick": forms.Select(attrs={"onchange": "this.form.submit();"}),
        }

While FirstForm derives from forms.Form, and SecondForm derives from forms.ModelForm “pick” in both forms should trigger a submission when selection changes.

Observation:

  1. FirstForm produces the desired results (the form submits when selection changes).
  2. SecondForm does nothing. The form does not submit when selection changes.

Question:
Why is SecondForm failing? Are widgets made from Models different from those in ordinary Forms?

I would look at the rendered html in the browser in both cases to see what the differences might be between the widgets being rendered.

The behavior you’re observing with FirstForm and SecondForm is related to the difference in how widgets are rendered and processed in a regular form (FirstForm) and a model form (SecondForm). The issue is not related to whether the form is derived from forms.Form or forms.ModelForm. Instead, it’s caused by the way the form fields and widgets are defined.

In FirstForm, you’re correctly using the widget attribute for the pick field to add an onchange attribute to the Select input field. This attribute triggers form submission when the selection changes, and it works as expected.

In SecondForm, you’re using the widgets attribute inside the Meta class to define the widget for the pick field. However, the widgets attribute is used to specify the default widgets for model form fields, and in this case, it doesn’t add the onchange attribute to the Select input field.

To make it work in SecondForm, you should set the widget attribute directly on the field definition in the form class, just like you did in FirstForm. Here’s how you can modify SecondForm to achieve the desired behavior:

class SecondForm(forms.ModelForm):
    pick = forms.ChoiceField(
        widget=forms.Select(attrs={"onchange": "this.form.submit();"})
    )

    class Meta:
        model = YourModelName  # Replace with your actual model
        fields = "__all__"

By setting the widget attribute for the pick field directly in the form class, you’ll ensure that the onchange attribute is added to the Select input field, and the form will submit when the selection changes. This should make SecondForm work as expected.

I have found the issue.

The fault is not from forms.ModelForm. Those forms were perfect. The issue was with the template. In the template, I had a button within the <form></form> tags that was named “submit”. That button was conflicting with the js method “this.form.submit()