【问题标题】:Django form with unknown number of checkbox fields and multiple actions具有未知数量的复选框字段和多个操作的 Django 表单
【发布时间】:2013-11-25 16:27:32
【问题描述】:

我需要有关表单的帮助,该表单看起来像 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('')

【问题讨论】:

    标签: django django-models django-forms django-templates django-views


    【解决方案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】:

        我在使用类基础视图并遍历 Django HTML 模板中未知大小的列表时遇到了同样的问题。

        此解决方案使用“发布”并为我工作。我把它放在这里是因为上述解决方案很有帮助,但并没有为我解决循环问题。

        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
        

        【讨论】:

        • 原谅我的新手,但它怎么知道从哪个模型中获取复选框的数据?
        • @dbinott 你说的是在显示复选框信息时还是在提交表单后?
        • 当它显示复选框信息时。我正在尝试输出按专辑分组的歌曲列表,并且需要能够检查每首歌曲。
        • 在你的类中创建一个名为 get_context_data(self, **kwargs) 的函数。在内部,您可以获取上下文数据并设置复选框要使用的数据。例如。 context[checkbox_list] = self.list_of_checkbox_items 然后您可以使用变量 'checkbox_list' 遍历或访问模板中的数据 这是 django 文档中的一个很好的解释:class based views with mixin
        • @dbinott 也可以设置模型,你可以在类的顶部使用其他变量初始化:class AuthorDetail(FormMixin, DetailView): model = Author form_class = AuthorInterestForm def get_context_data() ...
        【解决方案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)
        

        然后在该页面的视图方法的 post 部分中,您可以获得作为选择对象列表返回的选定选项,并使用 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
        

        如果没有选择任何组,这可能仍然需要一些逻辑,但应该足以开始。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-08-10
          • 2015-06-06
          • 1970-01-01
          • 2011-09-22
          • 1970-01-01
          相关资源
          最近更新 更多