博客五部曲之二 - 高级博客


1187 浏览 5 years, 4 months

22 删除权限和Http状态码

版权声明: 转载请注明出处 http://www.codingsoho.com/

上面的实现中,删除帖子是并没有判断用户,这就意味着你可以删除任何人的帖子,这显然是不合理的
而且删除时并没有判断帖子是否存在,这些将在本节中进行处理。

一个严重的问题是我以为子评论的content_type是父评论,但实际好像不是,看了一下全是Post,需要重新理解一下
content_type都是post,用GenericForeignKey是让它支持对各种内容进行评论包括评论本身,但是本课程的content_type即使对于嵌套评论还是帖子本身,它用了parent去链接父评论

修改后的comment_delete函数如下

def comment_delete(request, id):
    # obj = get_object_or_404(Comment, pk=id) # only for root post ModelManager
    try:
        obj = Comment.objects.get(id=id)
    except:
        raise Http404
    if obj.user != request.user:
        # messages.success(request,"You don not have permission to view this")
        # raise Http404
        response = HttpResponse("You don't have permission to view")
        response.status_code = 403
        return response
    if request.method == "POST":
        parent_obj_url = obj.content_object.get_absolute_url()
        obj.delete()
        messages.success(request, "This has been deleted")
        return HttpResponseRedirect(parent_obj_url)
    context = {
        "object":obj,
    }
    return render(request, "confirm_delete.html", context)

说一下修改的几个地方

  1. 实例获取从get_object_or_404改成了Comment.objects.get,如果回顾一下CommentManger,我们继承了all函数,它只包含根评论,但删除时我们需要支持删除任意评论,所有修改为新的函数,原函数会调用all函数。
  2. 加入用户判断,如果帖子不是当前用户创建的,则报错返回错误代码403 (没有权限)。一般情况下不应该走到这个分支,因为我们接下来会在模板里针对这种情况关闭删除入口。

修改模板comment_thread.html

<footer>via {{child_comment.user }} | {{child_comment.timestamp|timesince}} ago{% if request.user == child_comment.user%}<a href="{{child_comment.get_delete_url}}">| Delete</a>{% endif %}</footer>

仅当前用户和发布评论者不是同一人,显示删除按钮,并附带删除链接,该链接和我们常用的get_absolute_url用法相似,所以在模型里同样添加get_delete_url函数

class Comment(models.Model):
    def get_delete_url(self):
        return reverse("comments:delete", kwargs={"id":self.id})

这样,仅当评论用户和当前用户同一个人时才显示删除入口,并在视图处理中允许这个操作,否则报错403.