|
|
<<<<<<< HEAD
|
|
|
# Create your views here.
|
|
|
# 导入Django核心模块、异常类、视图工具及项目内模型/表单
|
|
|
from django.core.exceptions import ValidationError # Django内置验证异常类,用于抛出自定义验证错误
|
|
|
from django.http import HttpResponseRedirect # 用于重定向HTTP响应(如提交后跳回文章页)
|
|
|
from django.shortcuts import get_object_or_404 # 快捷查询:找到数据返回对象,找不到返回404页面
|
|
|
from django.utils.decorators import method_decorator # 用于给类视图的方法添加装饰器
|
|
|
from django.views.decorators.csrf import csrf_protect # CSRF保护装饰器:防止跨站请求伪造攻击
|
|
|
from django.views.generic.edit import FormView # 通用表单视图类:简化表单提交、验证、处理的逻辑
|
|
|
=======
|
|
|
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
|
|
|
>>>>>>> ZYY_branch
|
|
|
|
|
|
# 导入项目内关联模型和表单:用户、文章、评论表单、评论模型
|
|
|
from accounts.models import BlogUser
|
|
|
from blog.models import Article
|
|
|
from .forms import CommentForm # 评论功能的表单类(之前定义的CommentForm)
|
|
|
from .models import Comment
|
|
|
|
|
|
|
|
|
class CommentPostView(FormView):
|
|
|
"""
|
|
|
评论提交的类视图:继承FormView,处理评论表单的展示、验证和数据保存
|
|
|
核心功能:接收用户提交的评论数据,验证合法性后保存到数据库,支持评论回复
|
|
|
"""
|
|
|
# 1. 类视图基础配置
|
|
|
form_class = CommentForm # 指定关联的表单类:使用CommentForm处理提交数据
|
|
|
template_name = 'blog/article_detail.html' # 指定表单渲染的模板:评论在文章详情页提交,故用文章详情模板
|
|
|
|
|
|
# 2. 给dispatch方法添加CSRF保护:所有请求(GET/POST)都经过CSRF验证
|
|
|
@method_decorator(csrf_protect)
|
|
|
def dispatch(self, *args, **kwargs):
|
|
|
"""
|
|
|
类视图的请求入口方法:所有请求都会先经过此方法
|
|
|
作用:调用父类的dispatch逻辑,同时应用CSRF保护
|
|
|
"""
|
|
|
return super(CommentPostView, self).dispatch(*args, **kwargs)
|
|
|
|
|
|
# 3. 处理GET请求:当用户以GET方式访问该视图时触发
|
|
|
def get(self, request, *args, **kwargs):
|
|
|
"""
|
|
|
GET请求逻辑:不处理表单提交,直接重定向到对应的文章详情页的评论区
|
|
|
避免用户直接通过URL以GET方式访问该视图时出现异常
|
|
|
"""
|
|
|
# 从URL路径参数中获取文章ID(kwargs对应URL中的<int:article_id>)
|
|
|
article_id = self.kwargs['article_id']
|
|
|
# 查询对应的文章:找不到则返回404
|
|
|
article = get_object_or_404(Article, pk=article_id)
|
|
|
# 获取文章详情页的绝对URL,并拼接评论区锚点(#comments,跳转到页面评论区域)
|
|
|
url = article.get_absolute_url()
|
|
|
# 重定向到文章详情页的评论区
|
|
|
return HttpResponseRedirect(url + "#comments")
|
|
|
|
|
|
# 4. 处理表单验证失败的逻辑:当form.is_valid()为False时触发
|
|
|
def form_invalid(self, form):
|
|
|
"""
|
|
|
表单数据验证失败(如评论内容为空、格式错误)时的处理
|
|
|
作用:重新渲染文章详情页,带上错误的表单对象(前端显示错误提示)
|
|
|
"""
|
|
|
# 获取URL中的文章ID,查询对应的文章
|
|
|
article_id = self.kwargs['article_id']
|
|
|
article = get_object_or_404(Article, pk=article_id)
|
|
|
|
|
|
# 渲染模板:传递错误的表单对象(form)和文章对象(article),前端可显示错误信息
|
|
|
return self.render_to_response({
|
|
|
'form': form, # 带有错误信息的表单
|
|
|
'article': article # 当前文章对象(用于渲染文章详情)
|
|
|
})
|
|
|
|
|
|
# 5. 处理表单验证成功的逻辑:当form.is_valid()为True时触发(核心业务逻辑)
|
|
|
def form_valid(self, form):
|
|
|
"""提交的数据验证合法后的逻辑:保存评论数据到数据库,处理评论状态和回复关联"""
|
|
|
# 1. 获取当前登录用户(评论作者)
|
|
|
user = self.request.user # 从请求对象中获取登录用户
|
|
|
author = BlogUser.objects.get(pk=user.pk) # 通过用户ID查询完整的BlogUser对象
|
|
|
|
|
|
# 2. 获取当前评论对应的文章
|
|
|
article_id = self.kwargs['article_id'] # 从URL参数获取文章ID
|
|
|
article = get_object_or_404(Article, pk=article_id) # 查询文章,不存在则404
|
|
|
|
|
|
# 3. 验证文章评论状态:若文章关闭评论或处于草稿状态,抛出验证错误
|
|
|
# 假设'article.comment_status == 'c''表示关闭评论,'article.status == 'c''表示文章草稿
|
|
|
if article.comment_status == 'c' or article.status == 'c':
|
|
|
raise ValidationError("该文章评论已关闭.") # 抛出异常,前端可捕获并显示
|
|
|
|
|
|
# 4. 保存评论(先不提交到数据库,False表示暂存内存,后续补充字段)
|
|
|
comment = form.save(False) # form.save(False)返回评论对象,但不执行数据库INSERT
|
|
|
comment.article = article # 给评论关联文章(补充form中未包含的article字段)
|
|
|
|
|
|
# 5. 根据系统配置决定评论是否需要审核(直接启用或待审核)
|
|
|
from djangoblog.utils import get_blog_setting # 局部导入:避免循环引用
|
|
|
settings = get_blog_setting() # 获取博客系统全局配置(如comment_need_review)
|
|
|
if not settings.comment_need_review: # 若系统配置“评论无需审核”
|
|
|
comment.is_enable = True # 评论直接设为“启用”状态,前端可显示
|
|
|
|
|
|
comment.author = author # 给评论关联作者(补充form中未包含的author字段)
|
|
|
|
|
|
# 6. 处理评论回复:若表单中包含父评论ID,给当前评论关联父评论
|
|
|
if form.cleaned_data['parent_comment_id']: # 检查表单清理后的数据中是否有父评论ID
|
|
|
# 通过父评论ID查询对应的父评论对象
|
|
|
parent_comment = Comment.objects.get(
|
|
|
pk=form.cleaned_data['parent_comment_id']
|
|
|
)
|
|
|
# 注:原代码此处不完整(缺少赋值语句),正确逻辑应为“comment.parent_comment = parent_comment”
|
|
|
# 补充后才会将当前评论与父评论关联,实现回复功能
|
|
|
comment.parent_comment = parent_comment
|
|
|
|
|
|
# (原代码缺失:最终需调用comment.save()将评论数据提交到数据库,否则评论不会保存)
|
|
|
# comment.save() |