1👍
Django does this already, but Crispy only does this if you are using the Bootstrap v4 template pack. (Note: I am referencing Crispy 1.x in my answer. Crispy 2 was just released a couple of weeks ago and has significant changes that I haven’t reviewed yet, so my answer is only good for the 1.x version.)
If you look at the Django docs for the Field.choices
value, it shows that you can use a structure like this:
from django import forms
CHOICES = [
('vendredi 17 fevrier 2023', (
('20230217_0900', 'De 09:00 a 09:00'),
('20230217_0920', 'De 09:20 a 09:40'),
)),
('lundi 20 fevrier 2023', (
('20230220_1600', 'De 16:00 a 16:20'),
))
]
class MyForm(forms.Form):
my_field = forms.ChoiceField(widget=forms.widgets.RadioSelect, choices=CHOICES)
And when used in a Django template ({{ form }}
), the HTML is structured like you want:
<label for="id_my_field_0">My field:</label>
<ul id="id_my_field">
<li>vendredi 17 fevrier 2023
<ul id="id_my_field_0">
<li>
<label for="id_my_field_0_0"><input type="radio" name="my_field" value="20230217_0900" required="" id="id_my_field_0_0">
De 09:00 a 09:00</label>
</li>
<li>
<label for="id_my_field_0_1"><input type="radio" name="my_field" value="20230217_0920" required="" id="id_my_field_0_1">
De 09:20 a 09:40</label>
</li>
</ul>
</li>
<li>lundi 20 fevrier 2023
<ul id="id_my_field_1">
<li>
<label for="id_my_field_1_0"><input type="radio" name="my_field" value="20230220_1600" required="" id="id_my_field_1_0">
De 16:00 a 16:20</label>
</li>
</ul>
</li>
</ul>
But as for Crispy, it looks like it is only available if you are using their
Bootstrap v4 templates: https://github.com/django-crispy-forms/django-crispy-forms/blob/1.14.0/crispy_forms/templates/bootstrap4/layout/radioselect.html. Notice that they are looping over optgroups
on line 6. They don’t do this in the other template packs that they offer. And so if you are using one of those other template packs, then I think you need to write a custom widget/template. (I might have to investigate that a bit before being 100% sure, b/c there might be a way to do it in the Form.__init__
method, where you can dynamically update fields and widgets and such.)
Anyhow, this might not solve your problem, but hopefully it points you in the right direction. Let me know if I can offer any more help!