我有一个网站,我在数据库中有一堆记录。有两个字段Name
和Comment
。 models.py
:
class Db_test(models.Model):
name = models.CharField(max_length=50)
comment = models.CharField(max_length=200)
created = models.DateField(auto_now_add=True)
modified = models.DateField(auto_now=True)
class Meta:
db_table = "db_test"
我有一个页面,其中显示所有记录,旁边有一个删除按钮。我当前的页面:
我有以下views.py
(只是相关功能):
def delete(request):
objects = Db_test.objects.all()
items = []
if request.method == "POST":
print(int(list(request.POST)[-1]))
objects[int(list(request.POST)[-1])].delete()
for obj in objects:
items.append([obj.name, obj.comment])
return render(request, "models_test/delete.html", {"values": items})
相关的DTL部分:
{% for i in values %}
<form method="POST">
{% csrf_token %}
<p>{{ forloop.counter }}: {{ i.0 }}<input type="submit" name={{forloop.counter0}} value="X"></p>
<p>{{ i.1 }}</p>
</form>
{% endfor %}
除了偶尔引发错误外,所有这些都可以正常工作:
Traceback (most recent call last):
File "/home/mooncheesez/Desktop/django_projects/test_project/venv/lib/python3.4/site-packages/django/core/handlers/base.py", line 149, in get_response
response = self.process_exception_by_middleware(e, request)
File "/home/mooncheesez/Desktop/django_projects/test_project/venv/lib/python3.4/site-packages/django/core/handlers/base.py", line 147, in get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/mooncheesez/Desktop/django_projects/test_project/venv/testproject/models_test/views.py", line 32, in delete
print(int(list(request.POST)[-1]))
ValueError: invalid literal for int() with base 10: 'csrfmiddlewaretoken'
这条线是罪魁祸首:
objects[int(list(request.POST)[-1])].delete()
由于某些奇怪的原因,request.POST
仅包含csrf_token
,但不包含已提交的按钮。请注意,它偶尔也会发生。
我搜索了stackoverflow,我发现这篇帖子只是用复选框删除:Django: writing a view to delete an item with checkboxes
我该怎么做才能避免这种情况?对于我正在做的事情,有更好的选择吗?
答案 0 :(得分:1)
我会建议完全采用不同的方法。
在您的视图中,传递对象本身:
objects = Db_test.objects.all()
return render(request, "models_test/delete.html", {"values": objects})
在你的模板中:
{% for obj in object %}
<form method="POST">
{% csrf_token %}
<p>{{ forloop.counter }}: {{ obj.name }}<input type="submit" name="delete_items" value="{{ obj.pk }}"></p>
<p>{{ obj.comment }}</p>
</form>
{% endfor %}
再次在您看来:
if request.method == "POST":
# Fetch list of items to delete, by ID
items_to_delete = request.POST.getlist('delete_items')
# Delete those items all in one go
Db_test.objects.filter(pk__in=items_to_delete).delete()
一些一般性意见:
将[obj.name, obj.comment]
之类的列表传递给您的模板无法获得任何好处。只需传递对象本身。这将更容易维护。
根据自然数据库顺序进行更改绝对不是正确的方法 - 实际上它很危险且容易出错(例如,如果在渲染表单时将项目添加到数据库中会怎么样?)。您的数据库对象具有唯一ID以识别它们 - 使用它。
request.POST
是一本字典。将其转换为列表没有意义。如果您提供的输入列表都具有相同的名称,则可以使用getlist()
来获取它们。