Search code examples
djangodjango-formsdjango-templates

Can I override Django rendering checkbox inputs inside a label?


I'm trying to render a form which allows for multiple selections via checkboxes.

I've tried with django-multiselectfield (which I was already using) and the native CheckboxSelectMultiple widget.

If I have a simple form like so:

FAVORITE_COLORS_CHOICES = [
    ('blue', 'Blue'),
    ('green', 'Green'),
    ('black', 'Black'),
]

class SimpleForm(forms.Form):
    favorite_colors = forms.MultipleChoiceField(
        required=False,
        widget=forms.CheckboxSelectMultiple,
        choices=FAVORITE_COLORS_CHOICES,
    )

And if I render with widget tweaks like so:

{% render_field form.favorite_colors %}

I get the following HTML output

<div id="id_favorite_colors">
    <div>
        <label for="id_favorite_colors_0">
        <input class="form-control" id="id_favorite_colors_0" name="favorite_colors" placeholder="Your Name" type="checkbox" value="blue" />
        Blue</label>
    </div>
    <div>
        <label for="id_favorite_colors_1">
        <input class="form-control" id="id_favorite_colors_1" name="favorite_colors" placeholder="Your Name" type="checkbox" value="green" />
        Green</label>
    </div>
    <div>
        <label for="id_favorite_colors_2">
        <input class="form-control" id="id_favorite_colors_2" name="favorite_colors" placeholder="Your Name" type="checkbox" value="black" />
        Black</label>
    </div>
</div>

This is causing problems for the way I want to render my form. Is there any way I can force Django to output the input and then the label, so the html would be like so:

<div id="id_favorite_colors">
    <div>
        <input class="form-control" id="id_favorite_colors_0" name="favorite_colors" placeholder="Your Name" type="checkbox" value="blue" />
        <label for="id_favorite_colors_0">Blue</label>            
    </div>
    <div>
        <input class="form-control" id="id_favorite_colors_1" name="favorite_colors" placeholder="Your Name" type="checkbox" value="green" />
        <label for="id_favorite_colors_1">Green</label>            
    </div>
    <div>
        <input class="form-control" id="id_favorite_colors_2" name="favorite_colors" placeholder="Your Name" type="checkbox" value="black" />
        <label for="id_favorite_colors_2">Black</label>            
    </div>
</div>

I haven't found an easy answer to this and most of the discussions I've found are from 10 years ago or so.


Solution

  • You can try this out to find if it will work for you.

    Your template will look some thing like this

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <body>
        <div id="id_favorite_colors">
            {% for choice in form.favorite_colors %}
            <div>
                <label for="id_favorite_colours_{{ forloop.counter0 }}">{{choice.choice_label}}</label>
                {{ choice.tag }}
            </div>
            {% endfor %}
        </div>
    </body>
    </html>
    

    And your views.py will look like this

    def simple(request):
        form = SimpleForm()
        # Any custom logic you want to use for the form
        return render(request, "test.html", {"form":form})