django-Vue搭建博客:评论

这篇博客介绍了如何在Django中自建文章评论接口,包括创建评论模型、数据迁移、视图集、权限设置和序列化。通过实现IsOwnerOrReadOnly权限类确保只有评论作者才能修改评论,同时展示了接口测试,验证了功能的正确性。
摘要由CSDN通过智能技术生成

教程来源 杜塞-django-vue系列
博客链接 传送门

评论是博客作者和读者沟通的重要方式,也是墨客作者检验自身文章质量的手段,同时让网站实现交互。

虽然有很多方式可以将评论功能托管给第三方(本人推荐这么做),不过本着学习的目的吗,接下来就实现自己简单的文章评论接口。

准备工作

评论功能可以集成在article app内,但是为了下一张的二级评论和评论的评论,我们把评论独立出来:

# 创建评论模块并注册到配置文件:
(venv) E:\drf\drf_vue_blog>python manage.py startapp comment

#drf_vue_blog/settings.py
INSTALLED_APPS = [
    ···
    'comment'
]

创建评论模型:

# comment/models.py

from django.db import models
from django.utils import timezone
from article.models import Article
from django.contrib.auth.models import User

class Comment(models.Model):
    author = models.ForeignKey(
        User,
        on_delete=models.CASCADE,
        related_name='comment'
    )
    article = models.ForeignKey(
        Article,
        on_delete=models.CASCADE,
        related_name='comment'
    )
    comment = models.TextField()
    created = models.DateTimeField(default=timezone.now)
    
    class Meta:
        ordering=['-created']
    
    def __str__(self):
        return self.comment[:20]
    

模型包含一对一的作者外键,一对多的文章外键,评论内容,创建时间等四个字段。

数据迁移!!!

试图和序列化

视图集和之前章节没有太大区别:

from rest_framework import viewsets
from comment.models import Comment
from comment.serializers import CommentSerialize
from comment.permissions import IsOwnerOrReadOnly

class CommentViewSet(viewsets.ModelViewSet):
    queryset = Comment.objects.all()
    serializer_class = CommentSerialize
    permission_classes = [IsOwnerOrReadOnly]
    
    def perform_create(self, serializer):
        serializer.save(author = self.request.user)
    

接下来是写评论的权限。

评论对于用户的要求比文章松弛,非安全请求只需要是本人操作就好了。

因此定义一个所有人看,进本人可以更改的权限:

# comment/permissions.py

from rest_framework.permissions import BasePermission,SAFE_METHODS

class IsOwnerOrReadOnly(BasePermission):
    message = "You must be the owner to update."
    
    def has_permission(self, request, view):
        if request.method == SAFE_METHODS:
            return True
    def has_object_permission(self, request, view, obj):
        if request.method in SAFE_METHODS:
            return  True
        return obj.author == request.user
    

运行非安全请求时,由于需要验证当前评论的作者和当前登录用户是否为同一用户,这里会自动调用def has_object_permission(...)
方法,方法参数中的obj及评论模型的实例。

看起来只需要实现def has_object_permission(...)就可以了,但还有个小问题就是,此方法是晚于
def perform_created执行的。如果用户未登录新建评论,由于用户不存在,接口会抛出500错误。

本着出错就抛出错误提醒的原则,增加def has_permission(···)方法。此方法早于def perform_created执行,因此都能够对用户
登陆状态进行预检测。

功能这样就实现了,但是代码会重复,接下来就优化代码:

把权限类还改为以下:

# comment/permissions.py

from rest_framework.permissions import BasePermission, SAFE_METHODS


class IsOwnerOrReadOnly(BasePermission):
    message = "You must be the owner to update."

    def safe_methods_or_owner(self, request, func):
        if request.method in SAFE_METHODS:
            return True
        return func()

    def has_permission(self, request, view):
        return self.safe_methods_or_owner(
            request,
            lambda: request.user.is_authenticated
        )

    def has_object_permission(self, request, view, obj):
        return self.safe_methods_or_owner(
            request,
            lambda: obj.author == request.user
        )

用匿名函数将有函数体(闭包)作为参数,传递到 def safe_methods_or_owner(…) 方法里执行,效果和之前是完全一样的。

接下来就是注册路由和序列化器了。

路由:

# drf_vue_blog/urls.py
···
from comment.views import CommentViewSet
router.register(r'comment', CommentViewSet)

序列化器

# comment/serializers.py

from rest_framework import serializers
from comment.models import Comment
from user_info.serializers import UserDescSerializer

class CommentSerializer(serializers.ModelSerializer):
    url = serializers.HyperlinkedIdentityField(view_name='comment-detail')
    author = UserDescSerializer(read_only=True)
    
    class Meta:
        model = Comment
        fields = "__all__"
        extra_kwargs={'created':{'read_only':True}}
        

还是跟之前一样,url超链接字段让接口的跳转方便,author嵌套序列化器让其显示内容更丰富。

最后让评论通过文章接口显示出来:

# article/serializers.py
from comment.serializers import CommentSerializer
# 继承ArticleBaseSerializer
class ArticleDetailSerializer(ArticleBaseSerializer):
    id = serializers.IntegerField(read_only=True)
    comments = CommentSerializer(many=True,read_only=True)

这就完成了,代码量很少就完成了新功能。

测试

发送几个请求测试逻辑接口是否正确,

未登录状态新建评论:

>http POST http://127.0.0.1:8000/api/comment/ article=8 content="new comment"
HTTP/1.1 403 Forbidden
···
{
    "detail": "Authentication credentials were not provided."
}

用之前的Obama用户创建文章评论:、

>http -a Obama:admin123456 POST http://127.0.0.1:8000/api/comment/ article=8 content="new comment"
HTTP/1.1 201 Created
···
{
    "article": 8,
    "author": {
        "date_joined": "2021-06-13T06:47:00",
        "id": 2,
        "last_login": null,
        "username": "Obama"
    },
    "content": "new comment",
    "created": "2021-06-20T14:05:51.275911",
    "id": 1,
    "url": "http://127.0.0.1:8000/api/comment/1/"
}

用非本人用户xianwei用户更新评论:

>http -a xianwei:admin123456 PATCH http://127.0.0.1:8000/api/comment/1/ content="API"
HTTP/1.1 403 Forbidden
···
{
    "detail": "You must be the owner to update."
}

Obama删除评论:

>http -a Obama:admin123456 DELETE http://127.0.0.1:8000/api/comment/1/
HTTP/1.1 204 No Content
Allow: GET, PUT, PATCH, DELETE, HEAD, OPTIONS
Content-Length: 0
Date: Sun, 20 Jun 2021 06:09:08 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.9.4
Vary: Accept, Cookie
X-Content-Type-Options: nosniff

非本人无法对资源进行更改,很好的符合了预期逻辑。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值