Update views.py

master
pk6lqz7py 2 weeks ago
parent 9e99c6e056
commit cbe09f6b18

@ -1,14 +1,17 @@
#zyl:
# comments/views.py
import hashlib
# Django 视图文件:处理评论的创建和提交
import hashlib # 用于生成评论内容的 MD5 哈希,检测重复提交
from django.core.exceptions import ValidationError
from django.http import HttpResponseRedirect
from django.shortcuts import get_object_or_404
from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_protect
from django.views.generic.edit import FormView
from django.contrib import messages # 新增导入
from django.contrib import messages # Django 消息框架,用于显示一次性通知
from django.utils.timezone import now
from datetime import timedelta
from datetime import timedelta # 用于时间比较,检测短时间内重复提交
from accounts.models import BlogUser
from blog.models import Article
@ -17,71 +20,153 @@ from .models import Comment
class CommentPostView(FormView):
"""
评论发布视图基于表单类视图
功能特性
- CSRF 防护
- 处理 GET 请求重定向到文章页
- 表单验证长度重复提交
- 评论审核机制
- 嵌套评论回复支持
- 成功/错误消息提示
"""
# 指定使用的表单类
form_class = CommentForm
# 表单验证失败时使用的模板(即 article_detail.html
# 会在上下文中传递错误信息
template_name = 'blog/article_detail.html'
@method_decorator(csrf_protect)
def dispatch(self, *args, **kwargs):
"""
使用 CSRF 保护装饰器确保 POST 请求必须携带有效的 CSRF Token
防止跨站请求伪造攻击
"""
return super(CommentPostView, self).dispatch(*args, **kwargs)
def get(self, request, *args, **kwargs):
"""
处理 GET 请求用户直接访问此 URL 时重定向到文章详情页
逻辑
1. URL 参数获取 article_id
2. 查询文章对象404 保护
3. 重定向到文章详情页的评论区锚点
"""
article_id = self.kwargs['article_id']
article = get_object_or_404(Article, pk=article_id)
url = article.get_absolute_url()
return HttpResponseRedirect(url + "#comments")
return HttpResponseRedirect(url + "#comments") # #comments 是页面上的锚点
def form_invalid(self, form):
"""
表单验证失败时的处理
参数:
form: 包含错误信息的表单实例
返回:
重新渲染文章详情页显示表单错误
"""
article_id = self.kwargs['article_id']
article = get_object_or_404(Article, pk=article_id)
return self.render_to_response({
'form': form,
'article': article
'form': form, # 包含错误信息的表单对象
'article': article # 文章对象,模板需要
})
def form_valid(self, form):
"""
表单验证成功后的核心处理逻辑
流程
1. 检查文章评论状态
2. 检测重复提交30秒内相同内容
3. 保存评论根据审核设置决定是否立即显示
4. 处理嵌套评论parent_comment 关联
5. 发送成功消息并重定向
"""
"""提交的数据验证合法后的逻辑"""
# 获取当前请求用户
user = self.request.user
# 查询用户详细信息BlogUser 扩展了默认用户模型)
author = BlogUser.objects.get(pk=user.pk)
# 获取文章 ID 和文章对象
article_id = self.kwargs['article_id']
article = get_object_or_404(Article, pk=article_id)
# 检查文章评论状态
# 1. 检查文章评论状态
# comment_status == 'c' 表示评论已关闭
# status == 'c' 表示文章已关闭
if article.comment_status == 'c' or article.status == 'c':
messages.error(self.request, "该文章评论已关闭.")
return HttpResponseRedirect(article.get_absolute_url() + "#comments")
# 重复提交检查最近30秒内相同内容
# 2. 重复提交检查防止用户在30秒内重复提交相同内容
comment_body = form.cleaned_data['body'].strip()
body_hash = hashlib.md5(comment_body.encode()).hexdigest()
body_hash = hashlib.md5(comment_body.encode()).hexdigest() # 生成内容哈希
# 查询用户 30 秒内在该文章下发表的所有评论
recent_comments = Comment.objects.filter(
author=author,
article=article,
creation_time__gte=now() - timedelta(seconds=30)
)
# 遍历最近评论,对比内容哈希
for comment in recent_comments:
if hashlib.md5(comment.body.encode()).hexdigest() == body_hash:
messages.warning(self.request, "请勿重复提交相同评论内容!")
return HttpResponseRedirect(article.get_absolute_url() + "#comments")
# 保存评论
# 3. 保存评论到数据库commit=False 不立即提交)
comment = form.save(False)
comment.article = article
comment.article = article # 设置评论所属文章
# 4. 获取博客设置,检查是否需要审核
from djangoblog.utils import get_blog_setting
settings = get_blog_setting()
# 如果不需要审核则立即启用评论is_enable=True
# 否则保持默认 False待审核状态
if not settings.comment_need_review:
comment.is_enable = True
comment.author = author
comment.author = author # 设置评论作者
# 5. 处理嵌套评论:如果是回复,关联父评论
if form.cleaned_data['parent_comment_id']:
parent_comment = Comment.objects.get(
pk=form.cleaned_data['parent_comment_id'])
comment.parent_comment = parent_comment
# 保存评论到数据库commit=True
comment.save(True)
# 发送成功消息,显示在下一个页面
messages.success(self.request, "评论提交成功!")
# 6. 重定向到文章详情页,并定位到刚提交的评论位置
# 使用 #div-comment-{id} 锚点,前端模板需要有对应 ID 的元素
return HttpResponseRedirect(
"%s#div-comment-%d" %
(article.get_absolute_url(), comment.pk))
# 安全注意事项:
# 1. 用户身份验证:此视图假设用户已登录,实际应在 URL 配置或视图中添加 login_required
# 2. parent_comment_id 验证:应检查父评论是否属于同一文章,防止跨文章回复
# 3. 速率限制当前仅检查30秒重复建议增加更严格的速率限制如每小时最多评论数
# 4. 内容安全:评论内容需防范 XSS 攻击,应在模板层或模型层进行 HTML 转义
# 5. 邮件通知:发送邮件可能耗时,生产环境建议使用 Celery 异步任务
# 性能优化建议:
# 1. comment.save() 触发数据库写入,可考虑使用事务
# 2. 频繁查询 BlogUser 和 BlogSettings可添加缓存
# 3. get_max_articleid_commentid() 如果涉及复杂查询,可优化
Loading…
Cancel
Save