使用确认模板和POST方法

时间:2015-08-05 21:27:18

标签: django post confirmation

当我尝试使用DeleteView和POST方法一次性删除模型的多个对象时,我认为我正在进行标准操作,其间有一个确认模板。

好吧,要么我在电脑前坐得太久,要么Django不直接支持这种标准的方式。

正如Djangos docs和其他帖子所说,如果我使用GET方法,则仅显示确认模板(带有确认按钮)。但在我的情况下,我有一个ListView包含我的模型的所有对象,第一列是复选框,其值对应于各自的对象'标识。 我可以一次检查几个复选框,然后点击我的"删除所选项目"。表单使用POST方法(我不想使用GET)。

现在:在POST方法的情况下让DeleteView使用确认模板似乎会导致一些黑客入侵。几个小时后我没有成功。

这里最好的方法是什么?

我班级的标题如下:

class SomeItemConfirmDeleteView(DeleteView):
    template_name = 'confirm_delete_someitems.html'
    model = SomeItem
    success_url = reverse_lazy('list_someitems_url')
    items_to_delete = []

到目前为止已完成的步骤:

  1. 我覆盖了POST方法,这样如果我有一个列表,其中包含要从已选中的复选框中删除的所有ID,我会调用GET方法,以便显示确认模板。否则,"确认删除"按钮已在confirm_delete_someitems.html中按下。

    def post(self, request, *args, **kwargs):
        self.items_to_delete = self.request.POST.getlist('itemsToDelete')
        if not self.items_to_delete:
            return self.delete(request, *args, **kwargs)
        else:
            return self.get(self, *args, **kwargs)
    
  2. 我覆盖了get_object方法

    def get_object(self, queryset=None):
        return self.get_queryset()
    
  3. 我覆盖了get_queryset方法,以便将要删除的对象显示在confirm_delete_someitems.html的列表中。我从选中的复选框中获取对象,这些复选框名为" itemsToDelete"。

    def get_queryset(self):
        if not self.items_to_delete:
            queryset = super(ChargeParkConfirmDeleteView, self).get_queryset()
            self.queryset = # ... HOW TO GET THE OBJECTS TO DELETE??
            return self.queryset
        else:
            queryset = super(SomeItemConfirmDeleteView, self).get_queryset()
            self.queryset = queryset.filter(id__in=self.items_to_delete)
            return self.queryset
    
  4. 最后一步是它变得棘手:如何从confirm_delete_someitems.html的形式获取要删除的对象:

    <form action="" method="post">
            {% csrf_token %}
            {% trans 'The following objects as well as their related objects will be deleted. Are you sure?' %}
            <ul>
                {% for item in object %}
                    <li>{{ item }}</li>
                {% endfor %}
            </ul>
            <input type="submit" value="{% trans 'Confirm deletion' %}" />
        </form>
    

3 个答案:

答案 0 :(得分:1)

我现在找到了一个解决方案:我基本上添加了隐藏的输入字段,这些字段再次传输POST请求中已选中复选框的ID。

但如果有人发现更优雅的方式,我可以接受建议。 :)

<强> views.py

class SomeItemConfirmDeleteView(DeleteView):
    template_name = 'confirm_delete_someitems.html'
    model = SomeItem
    success_url = reverse_lazy('list_someitems_url')
    items_to_delete = []

    def get_queryset(self):
        queryset = super(ChargeParkConfirmDeleteView, self).get_queryset()
        self.queryset = queryset.filter(id__in=self.items_to_delete)
        return self.queryset

    def get_object(self, queryset=None):
        return self.get_queryset()

    def post(self, request, *args, **kwargs):
        self.items_to_delete = self.request.POST.getlist('itemsToDelete')
        if self.request.POST.get("confirm_delete"):
            # when confirmation page has been displayed and confirm button pressed
            queryset = self.get_queryset()
            queryset.delete() # deleting on the queryset is more efficient than on the model object
            return HttpResponseRedirect(self.success_url)
        elif self.request.POST.get("cancel"):
            # when confirmation page has been displayed and cancel button pressed
            return HttpResponseRedirect(self.success_url)
        else:
            # when data is coming from the form which lists all items
            return self.get(self, *args, **kwargs)

<强> confirm_delete_someitems.html:

<form action="" method="post">
    {% csrf_token %}
    {% trans 'The following objects as well as their related objects will be deleted. Are you sure?' %}
    <ul>
        {% for item in object %}
            <input type="hidden" value="{{ item.id }}" name="itemsToDelete" />
            <li><a href="{{ item.get_absolute_url }}">{{ item }}</a></li>
        {% endfor %}
    </ul>
    <input type="submit" class="btn btn-primary" value="{% trans 'Confirm deletion' %}" name="confirm_delete" />
    <input type="submit" class="btn btn-primary" value="{% trans 'Cancel' %}" name="cancel"/>
</form>

答案 1 :(得分:1)

感谢马克

这对我真的很有帮助。我还想通过post方法访问一些基于通用类的视图,例如DeleteView。但是,如果其他像我这样对Python知识不多的人正在寻找解决方案,那么我不得不更改一些事情,并想在这里添加。

我的html模板的一部分:

    <form method="post">{% csrf_token %}
                        <div class="form-group">
                                Sure, you want to delete that object?<br>
                                <br>
                                <strong>{{ object }}</strong>
                                {{ form.errors }}
                                <br>
                                <br>
                                <input type="hidden" name="confirm_delete" value="confirm_delete">
                                <button type="submit" class="btn btn-primary">Delete</button>
                        </div>
                </form>

和我的部分视图。py

class MV_Loeschen(DeleteView):
    template_name = templ_folder_name + 'mv_loeschen.html'
    model = MV
    success_url = reverse_lazy(url_app_name + 'mv_ausgabe_alle')

    def get_object(self, queryset=None):
        self.queryset = MV.objects.get(mv_id = self.to_delete)
        return self.queryset

    def post(self, request, mvpk):
        self.to_delete = mvpk
        if self.request.POST.get("confirm_delete"):
            queryset = MV.objects.get(mv_id = mvpk)
            queryset.delete()
            return HttpResponseRedirect(self.success_url)
        else:
            return self.get(self, mvpk)

那么,我在这里做什么? def post()方法向MV_Loeschen解释了如何处理发布请求。我通过邮寄表单从另一个页面收到一个参数mvpk,在该表单中,我告诉Django我要转到视图以删除ID为mvpk的MV对象。

然后我将self.to_delete设置为包含该ID(mvpk)。以后我在另一个定义中需要它。然后,我必须查看是否刚进入确认页面(您是否真的要删除该页面?),或者是否已经确认要删除该对象。第一种情况由结尾处的else分支(或您所谓的)处理。这似乎在内部引发了对DeleteView的调用,但是使用了GET方法。所以我抬头看着

https://docs.djangoproject.com/en/3.0/ref/class-based-views/generic-editing/#django.views.generic.edit.DeleteView

,还有我的python/site-packages/subfolders中的代码。

def依次使用get_object方法。但是这个def get_object不知道mvpk /我的MV对象的ID。因此,我从self.to_delete中获得了它(因此我需要在之前进行分配)。在这里,我采用的方法与Marc不同。

就像在他的解决方案get_object()中调用get_queryset()一样,它返回一个查询集,而我不理解他的解决方案中的超行,我只是直接在get_object()中获得了查询集

回到def post()。如果我已经确认要删除该对象,则必须获取该参数。我这样做是:

self.request.POST.get("confirm-delete")

再次感谢Marc,我想知道为什么我无法访问:

request.POST['confirm-delete']

直接。我不确定目前为止我是否完全理解这一点,但是至少您帮助我完成了这项工作。

然后,我可能在queryset的新设置中有多余的行。我不知道。然后分别删除查询集或MV对象。

最后,我重定向到success_url,为此不得不从HttpResponseRedirect导入django.http

答案 2 :(得分:0)

$(".delete-link").click(function(){
    confirm_box = confirm("Are you sure?");
    if(confirm_box == true)
        return true;
    else
        return false;
})