comments注释

pull/17/head
赵瑞萍 3 months ago
parent 3bb4711731
commit 31985976dc

@ -1,11 +1,21 @@
# 导入Django的path函数用于定义URL路径
from django.urls import path
# 导入当前应用下的views模块用于关联视图函数/类
from . import views
# 定义应用命名空间为"comments"用于在模板中通过命名空间引用URL避免多应用URL名称冲突
app_name = "comments"
# URL模式列表定义该应用的URL路由规则
urlpatterns = [
# 定义一个评论提交的URL路径
path(
# URL路径字符串包含一个整数类型的文章ID参数(article_id),用于指定评论所属的文章
'article/<int:article_id>/postcomment',
# 关联的视图类使用as_view()方法将类视图转换为可调用的视图函数
views.CommentPostView.as_view(),
name='postcomment'),
]
# 为该URL指定名称"postcomment",结合应用命名空间可通过"comments:postcomment"引用
name='postcomment'
),
]

@ -1,28 +1,54 @@
# 导入日志模块,用于记录程序运行中的信息和错误
import logging
# 导入Django的翻译函数用于实现多语言支持_为常用别名
from django.utils.translation import gettext_lazy as _
# 从项目工具模块导入获取当前站点信息和发送邮件的工具函数
from djangoblog.utils import get_current_site
from djangoblog.utils import send_email
# 创建当前模块的日志记录器,用于记录该模块相关的日志信息
logger = logging.getLogger(__name__)
def send_comment_email(comment):
"""
发送评论相关的邮件通知
功能说明
1. 向评论者发送感谢邮件
2. 若该评论是回复其他评论的即有父评论则向被回复的评论者发送回复通知邮件
"""
# 获取当前站点的域名如example.com
site = get_current_site().domain
# 邮件主题:感谢评论(支持多语言)
subject = _('Thanks for your comment')
# 构建评论所属文章的完整URL包含协议和域名
article_url = f"https://{site}{comment.article.get_absolute_url()}"
# 构建给评论者的邮件内容HTML格式支持多语言
# 使用占位符替换文章URL和标题
html_content = _("""<p>Thank you very much for your comments on this site</p>
You can visit <a href="%(article_url)s" rel="bookmark">%(article_title)s</a>
to review your comments,
Thank you again!
<br />
If the link above cannot be opened, please copy this link to your browser.
%(article_url)s""") % {'article_url': article_url, 'article_title': comment.article.title}
%(article_url)s""") % {
'article_url': article_url,
'article_title': comment.article.title
}
# 获取评论者的邮箱地址
tomail = comment.author.email
# 发送感谢邮件给评论者
send_email([tomail], subject, html_content)
try:
# 检查当前评论是否有父评论(即是否是回复其他评论)
if comment.parent_comment:
# 构建给被回复者的邮件内容HTML格式支持多语言
html_content = _("""Your comment on <a href="%(article_url)s" rel="bookmark">%(article_title)s</a><br/> has
received a reply. <br/> %(comment_body)s
<br/>
@ -30,9 +56,15 @@ def send_comment_email(comment):
<br/>
If the link above cannot be opened, please copy this link to your browser.
%(article_url)s
""") % {'article_url': article_url, 'article_title': comment.article.title,
'comment_body': comment.parent_comment.body}
""") % {
'article_url': article_url,
'article_title': comment.article.title,
'comment_body': comment.parent_comment.body # 被回复的评论内容
}
# 获取被回复评论者的邮箱地址
tomail = comment.parent_comment.author.email
# 发送回复通知邮件给被回复者
send_email([tomail], subject, html_content)
except Exception as e:
logger.error(e)
# 若发送过程中出现异常,记录错误日志
logger.error(e)

@ -1,63 +1,96 @@
# 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 # 用于抛出数据验证异常
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 .models import Comment
# 导入相关模型和表单
from accounts.models import BlogUser # 用户模型
from blog.models import Article # 文章模型
from .forms import CommentForm # 评论表单
from .models import Comment # 评论模型
class CommentPostView(FormView):
form_class = CommentForm
template_name = 'blog/article_detail.html'
"""评论提交处理的类视图"""
form_class = CommentForm # 指定使用的表单类
template_name = 'blog/article_detail.html' # 表单渲染和错误显示的模板
@method_decorator(csrf_protect)
def dispatch(self, *args, **kwargs):
"""
重写dispatch方法添加CSRF保护
使用method_decorator将csrf_protect装饰器应用到dispatch方法
确保表单提交经过CSRF验证防止跨站请求伪造攻击
"""
return super(CommentPostView, self).dispatch(*args, **kwargs)
def get(self, request, *args, **kwargs):
article_id = self.kwargs['article_id']
article = get_object_or_404(Article, pk=article_id)
url = article.get_absolute_url()
return HttpResponseRedirect(url + "#comments")
"""
处理GET请求
当通过GET访问评论提交URL时重定向到对应的文章详情页的评论区
"""
article_id = self.kwargs['article_id'] # 从URL参数中获取文章ID
article = get_object_or_404(Article, pk=article_id) # 获取对应的文章对象
url = article.get_absolute_url() # 获取文章的绝对URL
return HttpResponseRedirect(url + "#comments") # 重定向到文章详情页的评论锚点
def form_invalid(self, form):
article_id = self.kwargs['article_id']
article = get_object_or_404(Article, pk=article_id)
"""
表单数据验证失败时的处理
当表单提交的数据验证不通过如必填项为空格式错误等
重新渲染文章详情页并携带错误表单对象和文章对象方便前端显示错误信息
"""
article_id = self.kwargs['article_id'] # 获取文章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):
"""提交的数据验证合法后的逻辑"""
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)
"""
表单数据验证合法后的处理逻辑
当表单数据验证通过后执行评论保存等业务逻辑
"""
user = self.request.user # 获取当前登录用户
author = BlogUser.objects.get(pk=user.pk) # 根据用户ID获取对应的用户对象
article_id = self.kwargs['article_id'] # 获取文章ID
article = get_object_or_404(Article, pk=article_id) # 获取文章对象
# 检查文章评论状态:若文章评论关闭或文章状态为关闭,则抛出验证异常
if article.comment_status == 'c' or article.status == 'c':
raise ValidationError("该文章评论已关闭.")
# 保存表单数据但不提交到数据库commit=False以便后续补充字段
comment = form.save(False)
comment.article = article
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
comment.is_enable = True # 若无需审核,直接设置评论为启用状态
comment.author = author # 设置评论的作者
# 处理回复功能若存在父评论ID则关联父评论
if form.cleaned_data['parent_comment_id']:
parent_comment = Comment.objects.get(
pk=form.cleaned_data['parent_comment_id'])
comment.parent_comment = parent_comment
comment.save(True)
comment.save(True) # 最终保存评论到数据库
# 重定向到文章详情页中当前评论的锚点位置
return HttpResponseRedirect(
"%s#div-comment-%d" %
(article.get_absolute_url(), comment.pk))
(article.get_absolute_url(), comment.pk))
Loading…
Cancel
Save