目录
创建评论模型
blog/models.py
python
class Comment(models.Model):
post = models.ForeignKey(Post,on_delete=models.CASCADE,related_name='comments')
name = models.CharField(max_length=80)
email = models.EmailField()
body = models.TextField()
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
active = models.BooleanField(default=True)
class Meta:
ordering = ('created',)
def __str__(self):
return 'Comment by {} on {}'.format(self.name, self.post)
📌related_name让我们可以使用属性命名相互关联的对象。通过Post.comments.all()检索文章所有评论。如果没有定义related_name属性,Django将使用小写的模型名,后面跟着_set (comment_set)
更新数据库
python .\\manage.py makemigrations blog
python .\\manage.py migrate
将新模型添加到管理站点
python
from .models import Post,Comment
#...
@admin.register(Comment)
class CommentAdmin(admin.ModelAdmin):
list_display = ('name','email','post','created','active')
list_filter = ('active','created','updated')
search_fields = ('name','email','body')
模型关联 API 用法示例 | Django 文档 | Django (djangoproject.com)
创建一个表单来提交评论和验证输入数据
Django有两个基类来构建表单:Form和ModelForm。之前使用了第一种方法让您的用户通过电子邮件共享帖子。关于Form类更多内容,请看Django发送QQ邮件-CSDN博客
在本例中,使用 ModelForm,因为必须从Comment模型动态地构建表单。
blog/forms.py
python
from django import forms
from .models import Comment
#...
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = ('name','email','body')
添加一个视图来处理表单并将新注释保存到数据库中
编辑blog/views.py
python
from .forms import EmailPostForm,CommentForm
#...
def post_detail(request,year,month,day,post):
post = get_object_or_404(Post,slug=post,
status='published',
publish__year=year,
publish__month=month,
publish__day=day
)
comments = post.comments.filter(active=True)
new_comment = None
if request.method == 'POST':
comment_form = CommentForm(data=request.POST)
if comment_form.is_valid():
new_comment = comment_form.save(commit=False)
new_comment.post = post
new_comment.save()
else:
comment_form = CommentForm()
template = "blog/post/detail.html"
context = {
"post":post,
"comments":comments,
"new_comment":new_comment,
"comment_form":comment_form
}
return render(request,template,context)
将new_comment变量设置为None。将在创建新注释时使用该变量。如果视图被GET请求调用,用comment_form = CommentForm()构建一个表单实例。如果请求是POST,使用提交的数据实例化表单,并使用is_valid()方法验证它。如果表单无效,则呈现带有验证错误的模板。
如果表单有效,通过调用表单的save()方法创建一个新的Comment对象,并将其赋值给new_comment变量
- new_comment = comment_form.save(commit=False),save()方法创建表单链接到的模型实例,并将其保存到数据库中。如果使用commit=False,则创建了模型实例,但还没有将其保存到数据库中。
- new_comment.post = post,当把当前的文章分配给新建的评论(post)。
- new_comment.save(),写入数据库。
📌save()方法可用于ModelForm,但不能用于Form实例,因为它们没有链接到任何模型。
显示评论总数和评论列表
显示评论总数
/blog/templates/post/detail.html
html
{% with comments.count as total_comments %}
<h2>
{{ total_comments }} comment {{ total_comments|pluralize }}
</h2>
{% endwith%}
我们在模板中使用Django ORM,执行QuerySet comments.count()。
📌注意Django模板语言不使用圆括号来调用方法。
{% with %}标签允许我们为一个新变量赋值,该变量将在{% endwith %}标签之前可用。
📌{% with %}模板标签对于避免多次访问数据库或访问昂贵的方法非常有用。
显示评论列表
/blog/templates/post/detail.html
html
{% for comment in comments %}
<div class="comment">
<p class="info">
Comment {{ forloop.counter}} by {{ comment.name}}
{{ comment.created }}
</p>
{{ comment.body|linebreaks }}
</div>
{% empty %}
<p>There are no comments yet.</p>
{% endfor %}
使用{% for %}模板标签来循环遍历评论。如果评论列表为空,我们将显示一条默认消息,通知用户这篇文章还没有评论。{{forloop.counter}}包含每次迭代的循环计数器。然后,显示发布评论的用户的姓名、日期和评论正文。
创建评论表单,当表单成功提交时,显示一条成功消息
/blog/templates/post/detail.html
html
{% if new_comment %}
<h2>Your commet has been added.</h2>
{% else %}
<h2>Add a new comment</h2>
<form action="." method="post">
{{ comment_form.as_p}}
{% csrf_token %}
<p>
<input type="submit" value="Add comment">
</p>
</form>
{% endif %}
如果new_comment对象存在,我们将显示一条成功消息,因为注释已成功创建。否则,将为评论模型每个字段呈现带有段落<p>元素的表单,并包含POST请求所需的CSRF令牌。