django-crispy-forms / crispy-bootstrap4

Bootstrap 4 template pack for django-crispy-forms
MIT License
11 stars 5 forks source link

checkboxselectmultiple and radioselect repeats form's attributes #16

Closed bblanchon closed 1 year ago

bblanchon commented 1 year ago

Hi,

Thank you for this excellent project! I discovered this bug in the templates; please check it out.

Reproduction code

from django import forms

class DemoForm(forms.Form):
    language = forms.MultipleChoiceField(
        choices=[
            ("cpp", "C++"),
            ("py", "Python"),
            ("js", "JavaScript"),
        ],
        widget=forms.CheckboxSelectMultiple(),
    )

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.form_id = "FORM_ID"
        self.helper.form_class = "FORM_CLASS"
        self.helper.attrs["ATTR"] = "VALUE"

Actual vs expected output

<form ATTR="VALUE" class="FORM_CLASS" id="FORM_ID" method="post">
  <div id="div_id_language" class="form-group">
    <label>Language</label>
-    <div ATTR="VALUE" class="FORM_CLASS" id="FORM_ID">
+    <div>
      <div class="custom-control custom-checkbox">
        <input type="checkbox" class="custom-control-input" name="language" value="cpp" id="id_language_0">
        <label class="custom-control-label" for="id_language_0">C++</label>
      </div>
      <div class="custom-control custom-checkbox">
        <input type="checkbox" class="custom-control-input" name="language" value="py" id="id_language_1">
        <label class="custom-control-label" for="id_language_1">Python</label>
      </div>
      <div class="custom-control custom-checkbox">
        <input type="checkbox" class="custom-control-input" name="language" value="js" id="id_language_2">
        <label class="custom-control-label" for="id_language_2">JavaScript</label>
      </div>
    </div>
  </div>
</form>

As you can see, <form>'s attributes are inherited by the <div>.

I could trace this problem back to this line:

https://github.com/django-crispy-forms/crispy-bootstrap4/blob/f25758822da29cf5b1e1d96694bb651e93b8ff23/crispy_bootstrap4/templates/bootstrap4/layout/checkboxselectmultiple.html#L4

I think it should be field.flat_attrs instead of flat_attrs, but I'm not familiar enough with this project to be sure.

As far as I could tell, only two templates are affected checkboxselectmultiple.html and radioselect.html

Best regards, Benoit

bblanchon commented 1 year ago

This bug is also present in the test suite:

https://github.com/django-crispy-forms/crispy-bootstrap4/blob/f25758822da29cf5b1e1d96694bb651e93b8ff23/tests/results/bootstrap4/test_layout/test_fundamentals_example.html#L1-L5

As you can see, action="submit_survey", class="blueForms", and id="id-exampleForm" are repeated on the <div>.