数据表以及接口设计
个人博客
地址 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, 不建议关闭此验证。