当我尝试使用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 = []
到目前为止已完成的步骤:
我覆盖了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)
我覆盖了get_object方法
def get_object(self, queryset=None):
return self.get_queryset()
我覆盖了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
最后一步是它变得棘手:如何从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>
答案 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;
})