在Django中使用表单删除对象

5

我将要展示一个表格,每一行都应该有一个删除按钮,用于从表格中删除该元素。

我的问题是,我不确定如何将元素的id传递到视图中。

html:

{% for post in posts %}
    <div>
        <h3>Zuletzt ausgewählt:</h3>
        <p>published: <b>{{ post.pub_date }}</b>
        </p>
        <p>
            name: <b>{{ post.Name }}</b>
            anmeldung: <b>{{ post.get_Anmeldung_display }}</b>
            essen: <b>{{ post.get_Essen_display }}</b>
                <form action="" method="POST">
                  {% csrf_token %}
                  <input class="btn btn-default btn-danger" name="delete" type="submit" value="Löschen"/>
                </form>
        </p>
        <p>
            Email: <b>{{ post.Email }}</b>
        </p>
    </div>
{% endfor %}

views.py

if request.method == 'POST' and 'delete' in request.POST:
    Eintrag.objects.filter(pk=id).delete()
    return HttpResponseRedirect(request.path)  

所以,我需要将每篇文章的 post.pub_date 传递给视图,我该如何实现这一点?

那么我需要将每篇文章的post.pub_date传递给视图,我该如何实现呢? 不,是视图将post.pub_date传递给模板,为什么它还要将其传回去呢? - politinsa
嗯,按钮应该知道要删除哪篇文章 - 你说得对,将post.pub_date传递给按钮才是真正的问题。 - Sebastian
添加一个属性:<input id="{{ post.pk }}" ... />,并通过AJAX调用视图传递pk以进行删除。 - politinsa
3个回答

4
我的问题是,我不确定如何将元素的id传递给视图。
我可以想到两种方法来做这件事。我将一一介绍它们。
1. 在您的应用程序中创建一个专门用于删除对象的单独url路由:
('/post/<pk>/delete/', name="delete_post"),

然后将您的表单的 action 指向此 URL:

<form action="{% url 'delete_post' post.pk %}" method="POST">
    ...

最后,修改您的视图函数以接受pk参数:
def my_view(request, pk): 
    ...

2. 第二种方法是在表单中创建另一个字段,并将其传递给对象的主键(pk):
只需在您的表单中创建另一个字段即可。
<form action="" method="POST">
    <input type="hidden" value="{{ post.pk }}" name="pk">
    ...

然后在您的视图中,只需查看request.POST['pk']即可获取帖子的主键。


谢谢您的回答。我喜欢第二个想法,但是使用request.POST['pk']时出现了MultiValueDictKeyError错误,有什么想法吗? - Sebastian
啊,我忘了在输入框中添加“name =“ pk ””属性。 - xyres

3
一种非 AJAX 的实现方式,使用 Django 的通用视图非常容易,实现如下:

template.html

{% for post in posts %}
<div>
    <h3>Zuletzt ausgewählt:</h3>
    <p>published: <b>{{ post.pub_date }}</b>
    </p>
    <p>
        name: <b>{{ post.Name }}</b>
        anmeldung: <b>{{ post.get_Anmeldung_display }}</b>
        essen: <b>{{ post.get_Essen_display }}</b>
            <form action="" method="POST">
              {% csrf_token %}
              <input class="btn btn-default btn-danger" name="delete" type="submit" value="Löschen"/>
            </form>
    </p>
    <p>
        Email: <b>{{ post.Email }}</b>
    </p>
    <a href="/deleteurl/{{ post.pk }}">
        Delete this!
    </a>
</div>
{% endfor %}

当用户点击删除链接后,他们将被重定向到删除视图和模板,其URL看起来像这样“/deleteurl/1/”。

然后,您的视图、URL和处理删除的模板可能如下所示:

views.py

class DeleteMe(generic.DeleteView):
    template_name = 'deleteconfirmation.html'
    model = YourModel
    success_url = '/YourRedirectUrl/'

urls.py

url(r'^deleteurl/(?P<pk>\d+)/$', 
    views.DeleteMe.as_view(), name='deletemeview'),     

deleteconfirmation.html

<form action="" method="post">{% csrf_token %}
    <p>Are you sure you want to delete "{{ object }}"?</p>
    <input type="submit" value="Confirm" />
</form>

注意,这是不使用Ajax的情况下实现的。

视图和模板直接取自Django文档


0

我们优先使用POST,但我认为添加另一个表单是多余的。

django-allauth的电子邮件视图中找到解决方案。
虽然它不包括确认步骤(如文档中@HoneyNutIchiros提到的或更详细的, 或通过onclick),但它很有用。
他们给按钮添加了名称(action_remove),并在request.POST字典中检查它:

# account/email.html
<button type="submit" name="action_primary" >{% trans 'Make Primary' %}</button>
<button type="submit" name="action_send" >{% trans 'Re-send Verification' %}</button>
<button type="submit" name="action_remove" >{% trans 'Remove' %}</button>
...
<button name="action_add" type="submit">{% trans "Add E-mail" %}</button>

# account/views.py
class EmailView(AjaxCapableProcessFormViewMixin, FormView):
    ...
    def post(self, request, *args, **kwargs):
        ...
        if "action_add" in request.POST:
            res = super(EmailView, self).post(request, *args, **kwargs)
        elif "action_remove" in request.POST:
            res = self._action_remove(request)
        ...
        return res

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接