个人博客 Django 评论模块开发总结【二】数据表以及接口设计

数据表以及接口设计

个人博客 地址 https://www.charmcode.cn/article/2020-07-09_Comment
欢迎评论留言!

写之前先理清楚思路,各个表之间的关系是怎么样子的。
一个文章可以多个评论,一个用户也可以在一篇文章下评论多次
所以了 主要设计三张表

  • 文章表
  • 用户表
  • 评论表 (包含用户id 文章id)

Django orm model

这里了首先使用了django model 外键关联

  • 1 文章表model
class Article(models.Model):
    """
    文章
    """
    id = models.AutoField(primary_key=True)
    其他字段都省略了
    xxxxxx
    open_comment = models.BooleanField(default=True, verbose_name='是否开启评论')
  • 2 GitHub 用户表
class OAuthUser(models.Model):
    """
    第三方登录用户
    """
    id = models.AutoField(primary_key=True)
    username = models.CharField(max_length=128, unique=True, blank=True, null=True, verbose_name='用户名')
    avatar = models.CharField(max_length=256, blank=True, null=True, verbose_name='用户头像')
    origin = models.CharField(max_length=256, blank=True, null=True, verbose_name='来源')
    add_time = models.DateTimeField(default=datetime.now, verbose_name='添加时间')
  • 3 评论表
class Comment(models.Model):
    """
    文章评论
    """
    content = models.TextField(verbose_name='评论内容')
    oauth_user = models.ForeignKey(OAuthUser, blank=True, null=True,verbose_name='用户', on_delete=models.CASCADE)
    add_time = models.DateTimeField(auto_now_add=True, verbose_name='发布时间')
    article = models.ForeignKey(Article, blank=True, null=True, verbose_name='文章', on_delete=models.CASCADE)
    pid = models.ForeignKey('self', blank=True, null=True, verbose_name='父级评论', on_delete=models.CASCADE)

评论接口设计

按照需求,就只有两个接口,一个获取评论,一个增加评论,使用了Django 视图类的写法,就用一个类用get 和 post区分

from django.views.generic import View

class CommentView(View):
    """
    评论
    """

    def get(self, request):
        article_url = request.GET.get("article_url")
        try:
            article_id = Article.objects.filter(open_comment=True).get(article_url=article_url)
            comment_info_list = Comment.objects.filter(article=article_id).all()[:50]
            comment_list = []
            for info in comment_info_list.values_list("content", "user_name", "add_time"):
                comment_list.append({
                    "content": info[0],
                    "userInfo": OauthUser.fetch_login_user_info(info[1]),
                    "time": info[2].strftime("%Y-%m-%d %H:%M:%S")
                })
            return JsonResponse({"code": 200, "data": comment_list, "message": "success"})

        except Article.DoesNotExist:
            return JsonResponse({"code": 400})

    def post(self, request, *args, **kwargs):
        # 获取json参数
        try:
            json_res = json.loads(request.body.decode())
        except json.decoder.JSONDecodeError:
            return JsonResponse({"code": 500, "message": "传输json格式数据"})

        github_username = json_res.get("github_username")
        article_url = json_res.get("article_url")
        comment_content = json_res.get("comment_content")

        # 获取上次评论 时间 如果有直接
        last_time = cache.get(f"{github_username}_commit_time")
        if last_time:
            return JsonResponse({"code": 400, "message": "接口访问频率过快, 如果日志有恶意刷的话,考虑加验证码了!"})

        if github_username and article_url and comment_content:
            # 过滤内容取前100个字符
            comment_content = self.check_comment(comment_content[:100])
            try:
                # 获取对应的 用户 和 文章 model实例
                article_id = Article.objects.filter(open_comment=True, category__active=True, is_open=True).get(
                    article_url=article_url)
                user_id = OauthUser.objects.get(username=github_username)
            except (Article.DoesNotExist, OauthUser.DoesNotExist):
                return JsonResponse({"code": 400, "message": "参数错误没有对应的文章或者用户"})
            else:
                com_obj = Comment(content=comment_content, user_name=user_id, article=article_id)
                com_obj.save()
                # 缓存 10 秒
                cache.set(f"{github_username}_commit_time", int(time.time()), 10)

                return JsonResponse({"code": 200, "message": "保存ok"})
        else:
            return JsonResponse({"code": 500, "message": "有问题"})

    @staticmethod
    def check_comment(content):
        import re
        content = re.sub(r"[\"\\/*\'=\-#;<>+%$()!]", "", content)
        return content

有几个点

  • 限制当前用户评论频率,后续考虑IP,验证码之类的
  • 记得正则过滤用户输入数据,防止sql注入之类的。
  • Django post请求记得携带csrf_token, 不建议关闭此验证。
posted @ 2020-08-25 21:55  王小右  阅读(455)  评论(0编辑  收藏  举报