Форма Django с неизвестным количеством полей флажка и несколькими действиями
Мне нужна помощь с формой, которая выглядит как входящая почта Gmail и имеет несколько действий. Существует список элементов, и я хочу обернуть его формой, так как каждый элемент имеет флажок перед линией. Поэтому, когда пользователь выбирает несколько элементов, он может щелкнуть по двум кнопкам с различными действиями, например, удалить и пометить прочитанные.
<form action="">
{% for item in object_list %}
<input type="checkbox" id="item.id">
{{ item.name }}
{% endfor %}
<button type="submit" name="delete">Delete</button>
<button type="submit" name="mark_read">Mark read</button>
</form>
Я могу найти кнопку отправки, которую пользователь нажимает, если используется if 'delete' in request.POST
, но я не могу обратиться к любой форме, потому что форма Django не может быть определена с неизвестным количеством полей, как я думаю. Итак, как я могу обрабатывать выбранные элементы в поле зрения?
if request.method == 'POST':
form = UnknownForm(request.POST):
if 'delete' in request.POST:
'delete selected items'
if 'mark_read' in erquest.POST:
'mark selected items as read'
return HttpResponseRedirect('')
Ответы
Ответ 1
Несколько флажков с одинаковым именем - все те же поля.
<input type="checkbox" value="{{item.id}}" name="choices">
<input type="checkbox" value="{{item.id}}" name="choices">
<input type="checkbox" value="{{item.id}}" name="choices">
вы можете собирать и группировать их с помощью одного поля формы django.
class UnknownForm(forms.Form):
choices = forms.MultipleChoiceField(
choices = LIST_OF_VALID_CHOICES, # this is optional
widget = forms.CheckboxSelectMultiple,
)
В частности, вы можете использовать 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()
Ответ 2
Я не могу прокомментировать решение Thomas, поэтому я делаю это здесь.
Для ModelMultipleChoiceField имя аргумента не является выбором, кроме набора запросов.
Итак, чтобы взять последний пример:
class UnknownForm(forms.Form):
choices = forms.ModelMultipleChoiceField(
choices = queryset_of_valid_choices, # not optional, use .all() if unsure
widget = forms.CheckboxSelectMultiple,
)
Ответ 3
У меня была эта же проблема, используя базовое представление класса и повторяя список неизвестного размера в HTML-шаблоне Django.
Это решение использует "пост" и работает для меня. Я делаю это здесь, потому что вышеупомянутые решения были полезны, но не решили проблему с циклом для меня.
Шаблон HTML:
<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>
Форма:
class MyForm(forms.Form):
my_object = forms.MultipleChoiceField(
widget=forms.CheckboxSelectMultiple,
)
В представлении, основанном на классе, обращайтесь к данным POST с помощью функции post. Это позволит получить доступ к списку ваших отмеченных элементов, вашего контекста и других данных формы.
Вид:
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
Ответ 4
Я нашел, что это очень полезно при добавлении групп или разрешений пользователю.
Убедитесь, что у вас есть стандартные группы django и разрешения, включенные в ваше представление для страницы.
from django.contrib.auth.models import Permission, Group
Если вы извлекаете выбор из таблицы базы данных, вы можете использовать объект формы django с виджетами, чтобы динамически загружать все доступные варианты. Вам также необходимо убедиться, что ваши имена форм совпадают с именем модели.
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)
Затем в почтовом разделе метода просмотра для этой страницы вы можете получить выбранные варианты, возвращенные как список объектов выбора, и добавить их к объекту пользователя с циклом for.
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
Это может по-прежнему нуждаться в некоторой логике, если группы не выбраны, но должно быть достаточно для начала.