Django评论系统

目录

创建评论模型

将新模型添加到管理站点

创建一个表单来提交评论和验证输入数据  

显示评论总数和评论列表

创建评论表单,当表单成功提交时,显示一条成功消息


创建评论模型

blog/models.py

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

将新模型添加到管理站点

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

from django import forms
from .models import Comment

#...

class CommentForm(forms.ModelForm):

    class Meta:
        model = Comment
        fields = ('name','email','body')

添加一个视图来处理表单并将新注释保存到数据库中  
编辑blog/views.py

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

    {% 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

    {% 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

    {% 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令牌。