50👍
Easiest would be if you define the whole form in a HTML template. You should be able to iterate over a field’s values in a template like that:
{% for value, text in form.hikers.field.choices %}
{{ value }}: {{ text }}
{% endfor %}
14👍
Try this solution :
<ul>
{% for choice in form.my_choice_field.field.choices %}
<li>
<input type="radio" name="my_choice_field" value="{{choice.0}}"
{% ifequal form.my_choice_field.data choice.0 %}
checked="checked"
{% endifequal %}/>
<label for="">{{choice.1}}</label>
</li>
{% endfor %}
</ul>
see this link : http://www.ilian.io/django-forms-choicefield-and-custom-html-output/
- [Django]-How to pass django rest framework response to html?
- [Django]-Django: Open uploaded file while still in memory; In the Form Clean method?
- [Django]-Django filter JSONField list of dicts
9👍
This is surprisingly tricky, but you can do it using ModelMultipleChoiceField
, CheckboxSelectMultiple
, and a custom template filter. The form and widget classes get most of the way there, but the template filter works out which widget to give you for each instance in the queryset. See below…
Generic solution
# forms.py
from django import forms
from .models import MyModel
class MyForm(forms.Form):
my_models = forms.ModelMultipleChoiceField(
widget=forms.CheckboxSelectMultiple,
queryset=None)
def __init__(self, *args, **kwargs):
super(MyForm, self).__init__(*args, **kwargs)
self.fields['my_models'].queryset = MyModel.objects.all()
# myapp/templatetags/myapp.py
from django import template
from copy import copy
register = template.Library()
@register.filter
def instances_and_widgets(bound_field):
"""Returns a list of two-tuples of instances and widgets, designed to
be used with ModelMultipleChoiceField and CheckboxSelectMultiple widgets.
Allows templates to loop over a multiple checkbox field and display the
related model instance, such as for a table with checkboxes.
Usage:
{% for instance, widget in form.my_field_name|instances_and_widgets %}
<p>{{ instance }}: {{ widget }}</p>
{% endfor %}
"""
instance_widgets = []
index = 0
for instance in bound_field.field.queryset.all():
widget = copy(bound_field[index])
# Hide the choice label so it just renders as a checkbox
widget.choice_label = ''
instance_widgets.append((instance, widget))
index += 1
return instance_widgets
# template.html
{% load myapp %}
<form method='post'>
{% csrf_token %}
<table>
{% for instance, widget in form.job_applications|instances_and_widgets %}
<tr>
<td>{{ instance.pk }}, {{ instance }}</td>
<td>{{ widget }}</td>
</tr>
{% endfor %}
</table>
<button type='submit' name='submit'>Submit</button>
</form>
Specific to you
It should work if you adjust the form like so:
class ClubForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
cluk_pk = kwargs.pop('club_pk')
super(ClubForm, self).__init__(*args, **kwargs)
self.fields['hikers'].queryset = Club.objects.filter(pk=club_pk)
class Meta:
model = Club
fields = ('hikers',)
widgets = {'hikers': forms.CheckboxSelectMultiple}
- [Django]-Django: Open uploaded file while still in memory; In the Form Clean method?
- [Django]-Removing 'Sites' from Django admin page
- [Django]-How do I run tests against a Django data migration?
4👍
Maybe help someone.
template.html
<!-- radio -->
<div class="form-group">
{{ form.field_name.label_tag }}
{% for pk, choice in form.field_name.field.widget.choices %}
<div class="custom-control custom-radio custom-control-inline">
<input id="id_{{form.field_name.name}}_{{ forloop.counter0 }}" name="{{form.field_name.name}}" type="{{form.field_name.field.widget.input_type}}" value="{{pk}}" class="custom-control-input"
{% ifequal form.field_name.data pk.0 %}
checked="checked"
{% endifequal %}/>
<label for="id_{{form.field_name.name}}_{{ forloop.counter0 }}" class="custom-control-label">{{ choice }}</label>
</div>
{% endfor %}
</div>
<!-- checkbox -->
<div class="form-group">
{{ form.field_name.label_tag }}
{% for pk, choice in form.field_name.field.widget.choices %}
<div class="custom-control custom-checkbox custom-control-inline">
<input id="id_{{form.field_name.name}}_{{ forloop.counter0 }}" name="{{form.field_name.name}}" type="{{form.field_name.field.widget.input_type}}" value="{{pk}}" class="custom-control-input"
{% ifequal form.field_name.data pk.0 %}
checked="checked"
{% endifequal %}/>
<label for="id_{{form.field_name.name}}_{{ forloop.counter0 }}" class="custom-control-label">{{ choice }}</label>
</div>
{% endfor %}
</div>
- [Django]-Django Footer and header on each page with {% extends }
- [Django]-Django filter JSONField list of dicts
- [Django]-Django: For Loop to Iterate Form Fields
2👍
Another example of a generic solution (template only):
{% for widget in form.field_name %}
<tr>
<th>
<label for="{{widget.id_for_label}}">
<input type="{{widget.data['type']}}" name="{{widget.data['name']}}" value="{{widget.data['value']}}" {% if widget.data['selected'] %}selected{% endif %} {% for k, v in widget.data['attrs'].items() %} {{k}}="{{v}}" {% endfor %}>
</label>
</th>
<td>
{{widget.choice_label}}
</td>
</tr>
{% endfor %}
Explanation:
Basically, you just iterate over form.field_name
and there you get an widget like this:
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__html__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'choice_label', 'data', 'id_for_label', 'parent_widget', 'renderer', 'tag', 'template_name'] ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__html__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'choice_label', 'data', 'id_for_label', 'parent_widget', 'renderer', 'tag', 'template_name']
where widget.data
contains all the needed info to build the input elements:
{'name': 'field_name', 'value': 1, 'label': 'Field name 1', 'selected': False, 'index': '0', 'attrs': {'id': 'id_field_name_0'}, 'type': 'checkbox', 'template_name': 'django/forms/widgets/checkbox_option.html'}
- [Django]-Get the list of checkbox post in django views
- [Django]-Nginx doesn't serve static
- [Django]-A field with precision 10, scale 2 must round to an absolute value less than 10^8
1👍
I think, you can define own widget class inherited from CheckboxSelectMultiple with your own render() method and customize html output.
See source code, line 690
It’ll be reusable in any template as well.
- [Django]-Django DRF with oAuth2 using DOT (django-oauth-toolkit)
- [Django]-The QuerySet value for an exact lookup must be limited to one result using slicing. Filter error
- [Django]-Cannot access django app through ip address while accessing it through localhost
1👍
This answer provides a custom form widget – TableSelectMultiple
– which sounds like what you want:
There’s also the original Django Snippet.
- [Django]-How can I access environment variables directly in a Django template?
- [Django]-Substring in a django template?
- [Django]-FileUploadParser doesn't get the file name
1👍
related ticket: https://code.djangoproject.com/ticket/9230
I made a widget that makes such a table: http://skyl.org/log/post/skyl/2011/01/wherein-the-inner-workings-of-the-deathstarwidget-are-revealed/
I’m here looking for a better solution still though 😀
- [Django]-Django Admin app or roll my own?
- [Django]-Django/DRF – 405 Method not allowed on DELETE operation
- [Django]-Django-rest-framework returning 403 response on POST, PUT, DELETE despite AllowAny permissions