按照计划,这一篇把评论功能添加到博客里。
实现思路
- 编写评论的数据库表model
- 将评论与文章关联
- 编写评论表单form
- 设置评论发表后的URL
- 编写发表评论的视图view
- 美化评论的排版template
Model
参考多数网站,评论系统需要展示以下信息:
- 昵称
- 内容
- 评论时间
为和文章关联,还需要一个article属性。
# models.py
class Comment(models.Model):
username = models.CharField('昵称',max_length=10)
content = models.TextField('评论内容')
created_time = models.DateTimeField('评论时间',auto_now_add=True)
article = models.ForeignKey(Article,verbose_name='文章',on_delete=models.CASCADE)
def __str__(self):
return self.content[:25]
所有外键属性(ForeignKey)都最好设置on_delete属性,设为models.SET_NULL表示删除某个文章(外键)则其下所有评论的外键设为null,设为models.CASCADE则表示删除文章后,会把其下所有评论都删除,这是默认设置。
当然,对数据库改动后,少不了两行命令:
python manage.py makemigrations blog
python manage.py migrate
Forms
当需要由网页输入信息提交至服务器时,就要用到表单,比如常见的登录、注册、评论等功能。关于表单,可以参阅官方文档Forms或中文文档。
博客的评论表单可以由评论模型生成,使用forms的ModelForm。首先在blog的文件夹里创建forms.py模块,并导入models。
# forms.py
from django import forms
from .models import Article,Comment
class CommentForm(forms.ModelForm):
class Meta:
'''设置Meta'''
model = Comment #设置表单form关联的模型model
fields = ('username','content') #设置在模板中渲染的字段
URL
# urls.py
urlpatterns = [
url(r'^$',views.IndexView.as_view(),name='index'),
...
url(r'^article/(?P<article_id>\d+)/comment/$',views.CommentView.as_view(),name='comment'),
]
View
django中也有表单处理的通用视图FormView,使用此视图数据有效时会定向到所指定渲染的模板,数据无效时会重新显示表单并带有错误提示。
# views.py
**from django.http import HttpResponseRedirect**
from django.shortcuts import render,**get_object_or_404**
from django.views.generic import ListView,DetailView,**FormView**
**from .forms import CommentForm**
class CommentView(FormView):
form_class = CommentForm
template_name = 'blog/detail.html'
#指定评论提交后渲染的模板文件
#评论成功后返回文章详情页
def form_valid(self,form):
#从当前url获取被评论的文章
target_article = get_object_or_404(Article,pk=self.kwargs['article_id'])
#返回生成实例,暂不保存评论
comment = form.save(commit=False)
comment.article = target_article #将评论与文章关联
comment.save()
# 用Article中定义的方法获取重定向的URL
self.success_url = target_article.get_absolute_url()
return HttpResponseRedirect(self.success_url)
代码中get_absolute_url()是在Article的模型中新增的方法,作用是获取当前文章的url。
# models.py
**from django.core.urlresolvers import reverse**
#创建文章模型
class Article(models.Model):
...
#新增方法,得到当前文章的url,用于CommentView
def get_absolute_url(self):
return reverse('blog:detail',kwargs={'article_id':self.pk})
同时,要把评论表单添加进ArticleView中,以在详情页渲染评论表单。
# views.py
class ArticleView(DetailView):
...
#把评论form添加到context
def get_context_data(self,**kwargs):
kwargs['comment_list'] = self.object.comment_set.all()
kwargs['form'] = CommentForm()
return super(ArticleView,self).get_context_data(**kwargs)
只需要再创建一个comment.html,并将其包含在detail.html中就可以了。
# comment.html
<html>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<body>
<hr />
<h1>Comment</h1>
<form method="post" action="{% url 'blog:comment' article.pk %}">
{% csrf_token %}
{% for field in form %}
{{ field }}
<br>
<br>
{% endfor %}
<button type="submit">Submit</button>
</form>
<hr />
{% for comment in comment_list %}
{{ comment.username }}
{{ comment.created_time }}
{{ comment.content }}
<a href="">Reply</a>
<hr />
{% endfor %}
</body>
</html>
# detail.html
<html>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<head><title>文章详情</title></head>
<body>
<h1 style='color:blue;'>
<a href=" {% url 'blog:index' %}">首页</a>
</h1>
<h3>{{article.title}}</h3>
{{article.text|safe}}
<br />
**{% include 'blog/comment.html' %}**
</body>
</html>
除了comment.html里写不了中文,其他运行起来妥妥的,截图如下:
这个画面实在让我提不起兴趣了,所以最近要专攻几天JS和CSS,之后的计划是:
- 画面美化
- 添加前端写博客的功能
- 添加一下如点赞、评论数、回复评论、归档等功能
- 后台添加一些方便管理的功能