36👍
Multiple checkboxes with the same name are all the same field.
<input type="checkbox" value="{{item.id}}" name="choices">
<input type="checkbox" value="{{item.id}}" name="choices">
<input type="checkbox" value="{{item.id}}" name="choices">
you can collect and aggregate them with a single django form field.
class UnknownForm(forms.Form):
choices = forms.MultipleChoiceField(
choices = LIST_OF_VALID_CHOICES, # this is optional
widget = forms.CheckboxSelectMultiple,
)
Specifically, you can use a ModelMultipleChoiceField.
class UnknownForm(forms.Form):
choices = forms.ModelMultipleChoiceField(
queryset = queryset_of_valid_choices, # not optional, use .all() if unsure
widget = forms.CheckboxSelectMultiple,
)
if request.method == 'POST':
form = UnknownForm(request.POST):
if 'delete' in request.POST:
for item in form.cleaned_data['choices']:
item.delete()
if 'mark_read' in request.POST:
for item in form.cleaned_data['choices']:
item.read = True; item.save()
7👍
I was having this same issue using a class base view and iterating through a list of unknown size in the Django HTML template.
This solution uses ‘post’ and works for me. I’m putting this here because the above solutions were helpful but didn’t solve the looping issue for me.
HTML Template:
<form action="" method="post">
{% for item in object_list %}
<input type="checkbox" value="{{item.id}}" name="my_object">
{{ item.name }}
{% endfor %}
<button type="submit" name="delete">Delete</button>
<button type="submit" name="mark_read">Mark read</button>
</form>
Form:
class MyForm(forms.Form):
my_object = forms.MultipleChoiceField(
widget=forms.CheckboxSelectMultiple,
)
In the class-based view, access the POST data using a post function. This will allow access to a list of your checked items, your context, and other form data.
View:
Class MyView(FormView):
template_name = "myawesometemplate.html"
form_class = MyForm
...
# add your code here
def post(self, request, *args, **kwargs):
...
context = self.get_context_data()
...
if 'delete' in request.POST:
for item in form.POST.getlist('my_object'):
# Delete
if 'mark_read' in request.POST:
for item in form.POST.getlist('my_object'):
# Mark as read
6👍
I can’t comment Thomas solution so I do it here.
For ModelMultipleChoiceField the argument name is not choices but queryset.
So to take the last example:
class UnknownForm(forms.Form):
choices = forms.ModelMultipleChoiceField(
choices = queryset_of_valid_choices, # not optional, use .all() if unsure
widget = forms.CheckboxSelectMultiple,
)
- Django admin inline many to many custom fields
- Get Celery to Use Django Test DB
- Django – authentication, registration with email confirmation
-1👍
I found this to be very useful when adding groups or permissions to a user.
Make sure that you have the default django groups and permissions included in your view for the page.
from django.contrib.auth.models import Permission, Group
If you are pulling the choices from a database table you can use a django form object with a widget to dynamically load all of the available choices. You also need to make sure that your form names are the same as the model name.
groups = forms.ModelMultipleChoiceField(label='Groups', required=False, queryset=Group.objects.all(), widget=forms.CheckboxSelectMultiple)
user_permissions = forms.ModelMultipleChoiceField(label='Permissions', required=False, queryset=Permission.objects.all(), widget=forms.CheckboxSelectMultiple)
Then in the post section of the view method for that page you can get the selected choices returned as a list of the choice objects, and add them to the user object with a for loop.
u.save() # required to save twice, so this saves the other form fields.
user.groups.clear()
u.user_permissions.clear()
# print('Group name:', form.cleaned_data['groups'])
for group in form.cleaned_data['groups']:
print(group) # Prints to your console for debugging
user.groups.add(group)
for permission in form.cleaned_data['user_permissions']:
print(permission) # Prints to your console for debugging
user.user_permissions.add(permission)
u.save() #This saves the groups and permissions
This may still need some logic if no groups are selected, but should be enough to get started.