评论板块的开发
涉及知识点:
- form表单设置css样式和输入框类型,数据清洗
- 服务端快速接受POST请求提交的form表单数据
- 前端模板中遍历form表单中的错误信息
- TemplateView的使用
- js返回上个页面
- 自定义模板标签
1.配置评论提交时的form表单 forms.py
from comment.models import Comment
from django import forms
# 如果不考虑样式,仅需定义model和fields即可
class CommentForm(forms.ModelForm):
# email = forms.CharField(
# label='Email',
# max_length=50,
# widget=forms.widgets.EmailInput(
# attrs={'class': 'form-control', 'style': 'width: 60%'}
# )
# )
content = forms.CharField(
label='内容',
max_length=500,
# 可以在定义form表单时设置限制和样式
widget=forms.widgets.Textarea(
attrs={'rows': 6, 'cols': 60, 'class': 'form-control'}
)
)
# 定义需要进行数据清洗的字段和规则
def clean_content(self):
content = self.cleaned_data.get('content') # 获取字段内容
if len(content) < 10:
raise forms.ValidationError('评论不可少于10个字')
return content
class Meta:
model = Comment
fields = ['content',] # 表单对象渲染时显示的字段
2.在Model层提供返回某篇文章下所有评论的接口
class Comment(models.Model):
# 省略其余代码
@classmethod
def get_by_target(cls, target):
return cls.objects.filter(target=target, status=cls.STATUS_NORMAL)
3. 视图层,完成提交评论功能
from comment.forms import CommentForm
from django.shortcuts import render, redirect
from django.urls import reverse
from django.views.generic import TemplateView
# 定义评论提交的视图类
class CommentView(TemplateView):
http_method_names = ['post'] # 限定该视图类仅提供post方法
template_name = 'comment/result.html'
def post(self, request, *args, **kwargs):
# 接受POST请求提交的form表单数据
comment_form = CommentForm(request.POST)
target = request.POST.get('target')
if comment_form.is_valid():
# 此处通过form表单对象创建了一个实例,不用再创建comment的对象了
instance = comment_form.save(commit=False)
instance.target = target
instance.nickname = request.user.first_name
instance.website = reverse('author', args=(request.user.id,))
email = request.user.email
instance.save()
succeed = True
return redirect(target)
else:
succeed = False
context = {
# 标记是否评论成功
'succeed': succeed,
# 若发生异常,form表单对象中会存入异常信息
'form': comment_form,
'target': target,
}
# 将数据渲染到响应对象和模板中
# 也可以直接用render(request, self.template_name, context=context)
return self.render_to_response(context)
4.配置评论响应界面,评论成功则返回原文章,失败则返回指定提示页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>评论结果页</title>
</head>
<body>
<div class="result">
{% if succeed %}
评论成功!
<a href="{{ target }}"></a>
{% else %}
评论失败:
<ul class="errorlist">
<!-- 遍历form表单中的错误信息 -->
{% for field, message in form.errors.items %}
<li>{{ message }}</li>
{% endfor %}
</ul>
<!-- JS返回上个页面 -->
<a href="javascript:window.history.back();">返回</a>
{% endif %}
</div>
</body>
</html>
5.抽象出评论模板组件
1.编写自定义标签:comment APP下新建templatetags目录,目录下新增__init__.py和comment_block.py
获取数据源 comment_block.py
from django import template
from comment.forms import CommentForm
from comment.models import Comment
# 自定义模板标签
register = template.Library()
# 配置评论模板,前端页面直接当成标签渲染
@register.inclusion_tag('comment/block.html')
def comment_block(target):
return {
# 自定义标签中默认没有request对象,因此需要手动将target添加到页面中
'target': target,
'comment_form': CommentForm,
'comment_list': Comment.get_by_target(target),
}
2.前端模板
<div class="comment">
<p>留言区</p>
<form action="/comment/" method="post" class="form-group">
{% csrf_token %}
<input type="hidden" name="target" value="{{ target }}">
{{ comment_form.as_p }}
<input type="submit" value="写好了">
</form>
<!-- 评论列表 -->
<p>留言板</p>
<ul class="list-group">
{% for comment in comment_list %}
<li class="list-group-item">
<div class="nickname">
<a href="{{ comment.website }}">
{% if comment.nickname %}
{{ comment.nickname }}
{% else %}
暂无昵称
{% endif %}
</a>
<span>{{ comment.created_time }}</span>
</div>
<div class="comment-content">
{{ comment.content }}
</div>
</li>
{% endfor %}
</ul>
</div>
6.使用自定义模板在详情页添加评论板块,其他页面要使用时直接使用模板标签即可
{% extends 'blog/base.html '%}
{% load comment_block %} <!-- 导入自定义模板标签 -->
{% block main %}
<!-- 省略其余代码 -->
{% comment_block request.path %}
{% endblock %}
7.配置url
参考:《Django企业开发实战》