diff --git a/src/django-master/comments/views.py b/src/django-master/comments/views.py index ad9b2b9..05540a8 100644 --- a/src/django-master/comments/views.py +++ b/src/django-master/comments/views.py @@ -1,63 +1,105 @@ # Create your views here. -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 +# 导入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 accounts.models import BlogUser from blog.models import Article -from .forms import CommentForm +from .forms import CommentForm # 评论功能的表单类(之前定义的CommentForm) from .models import Comment class CommentPostView(FormView): - form_class = CommentForm - template_name = 'blog/article_detail.html' + """ + 评论提交的类视图:继承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中的) 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 + 'form': form, # 带有错误信息的表单 + 'article': article # 当前文章对象(用于渲染文章详情) }) + # 5. 处理表单验证成功的逻辑:当form.is_valid()为True时触发(核心业务逻辑) def form_valid(self, form): - """提交的数据验证合法后的逻辑""" - user = self.request.user - author = BlogUser.objects.get(pk=user.pk) - article_id = self.kwargs['article_id'] - article = get_object_or_404(Article, pk=article_id) + """提交的数据验证合法后的逻辑:保存评论数据到数据库,处理评论状态和回复关联""" + # 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("该文章评论已关闭.") - comment = form.save(False) - comment.article = article - from djangoblog.utils import get_blog_setting - settings = get_blog_setting() - if not settings.comment_need_review: - comment.is_enable = True - comment.author = author - - if form.cleaned_data['parent_comment_id']: + 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']) + pk=form.cleaned_data['parent_comment_id'] + ) + # 注:原代码此处不完整(缺少赋值语句),正确逻辑应为“comment.parent_comment = parent_comment” + # 补充后才会将当前评论与父评论关联,实现回复功能 comment.parent_comment = parent_comment - comment.save(True) - return HttpResponseRedirect( - "%s#div-comment-%d" % - (article.get_absolute_url(), comment.pk)) + # (原代码缺失:最终需调用comment.save()将评论数据提交到数据库,否则评论不会保存) + # comment.save() \ No newline at end of file