Django 从帖子中删除对象(Bootstrap)

103 阅读2分钟

在使用 Django 和 Bootstrap 时,我试图实现一种从前端使用表单和 Bootstrap 删除对象的方法。警报框关闭了,但在页面刷新后对象仍然存在,并且没有在数据库中删除。想了解如何正确实现此操作。

以下是一些相关的代码示例:

forms.py

class DeleteAlertForm(forms.ModelForm):
    def is_valid(self):
        form = super(DeleteAlertForm, self).is_valid()
        for f, error in self.errors.iteritems():
            if f != '__all__':
                self.fields[f].widget.attrs.update({'class': 'error', 'value': strip_tags(error)})
        return form

    class Meta:
        model = Alert
        fields = []

views.py

@login_required
def delete(request, alert_id):
    if request.method == "POST":
        form = DeleteAlertForm(request.POST)
        if form.is_valid():  # checks CSRF
            a_id = request.POST.get('alert_id', False)
            alert = New.objects.get(pk=a_id)
            alert.delete()
            return HttpResponseRedirect("/")
    else:
        return redirect('/')
    return redirect('/')

template.html

<div class="alert alert-info alert-block">
<form action="/delete/" method="post">
{% csrf_token %}
<input type="hidden" value="{{alert.id}}" name="alert_id">
<button type="submit" class="close" data-dismiss="alert">×</button>
</form>
</div>

urls.py

url(r'^$/(?P<pk>\d+)/delete$', login_required(DeleteView.as_view(
    model=Alert,
    success_url='/',
    template_name='portal/alert_confirm_delete.html',))),

2、解决方案

解决方案1:使用 DeleteView

可以考虑使用 DeleteView。以下是实现此 URL 的方法:

url(r'^mymodel/(?P<pk>\d+)/delete/$', login_required(DeleteView.as_view(
    model=MyModel,
    success_url="/mymodel/deleted/",
    template_name="myapp/mymodel_confirm_delete.html",
))),

对于要删除的每个模型,你都需要实现类似的操作。但 urls.py 中只需要导入 DeleteView 即可。但是,你可以在所有模型中使用相同的模板和成功 URL。

解决方案2:使用 Django 和 Bootstrap 创建自己的删除模板

可以使用 Django 与自己的删除模板配合 Bootstrap 使用。由于用户界面和重定向与预期的一样,错误似乎在于你设置了错误的模型:New 在删除操作中,在你更新/发布修订后的 urls.py 后变得清晰。要运行删除操作的模型应该为 Alert。

在你的删除操作中,由主键 New 对应的条目组成的查询集被选择等于 alert_id。

  alert = New.objects.get(pk=a_id)

目标模型很可能是 Alert。若要使用 Alert 条目从 New 模型中获取条目,请在 New 模型中设置外键关系,如下所示:

class New(models.Model):
  alert = models.ForeignKey(Alert, verbose_name=_("Alert posts"))
  ....

Django 的对象关系映射器将创建一个名为 alert_id 的数据库字段,其中包含适当的关系约束和外键。之后不要忘记在 shell 中运行 syndb。例如,使用 manage.py syndb。

当 DEBUG 在 settings.py 中打开时,Django 可能默认抛出一个类似于以下内容的 DoesNotExist 异常:

In [2]: appname.models.New.objects.get(pk=-1)
---------------------------------------------------------------------------
DoesNotExist                              Traceback (most recent call last)
/usr/local/lib/python2.6/dist-packages/django/core/management/commands/shell.pyc in <module>()
----> 1 lead.models.Lead.objects.get(pk=-1)

/usr/local/lib/python2.6/dist-packages/django/db/models/manager.pyc in get(self, *args, **kwargs)
    129
    130     def get(self, *args, **kwargs):
--> 131         return self.get_query_set().get(*args, **kwargs)
    132
    133     def get_or_create(self, **kwargs):
....
DoesNotExist: Lead matching query does not exist.

虽然 Django 默认在 DEBUG 打开时向你显示异常,但你会立即在你的代码中重定向并且没有处理/输出异常。异常应该仍然被记录下来,并被写入日志文件,日志文件的具体位置取决于运行的服务器。你可以使用变量 LOGGING = {...} 在项目的 settings.py 中设置日志处理。请参阅 Django 手册中的日志记录。