美文网首页
2.2 创建一个评论系统

2.2 创建一个评论系统

作者: gznb | 来源:发表于2020-07-20 16:41 被阅读0次

    创建一个评论系统

    你将建立一个 评论系统,其中用户将能够评论帖子,去创建评论系统,你需要做下面的这些:

      1. 创建一个模型去保存评论。
      1. 创建提交评论的表单,并且验证输入数据。
      1. 添加处理表单并且在数据库中保存一个新评论的视图。
      1. 编辑帖子详情模板去显示评论列表,和添加新评论的表单。

    1. 创建模型

    首先,创建的一个模型去存储评论,在你的 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 f'Comment by {self.name} on {self.post}'
    

    这是你的 Comment 模型。它包含一个 ForeignKey 来将一个评论与唯一的一个帖子联系起来。这个多对一关系定义在 Comment 模型中,因为每一个评论都在一个帖子中发表,并且每一个帖子可能有多个评论。

    related_name 属性提供了一个 name 的属性,在关系中使用这个 name 属性可以返回一个关系对象。在定义这个之后,你可以使用comment.post检索一个评论对象的帖子,并且使用 post.comments.all() 检索一个帖子的所有评论。如果你没有定义这个 related_name 属性,Django 将使用小写的模型名称,然后通过_set(即comment_set)去命名与 模型对象 相关联的对象 的关系,该关系已在其中定义。

    你可以在这个链接学习更多关于 多对一关系。

    你有包含一个 active 布尔字段,你可以手动的让不适当的评论失效。默认情况下,使用created字段按时间顺序对评论进行排序。

    新的 Comment 模型它现在仅仅被创建还没有同步创建到数据库中。运行下面的命令去生成一个新的迁移,思考新模型的创建:
    python manage.py makemigrations

    你可以看到下面的输出:


    image.png

    Django 在 blog 应用程序的 migrations 目录中生成了一个 00002_comment.py 文件。现在你需要创建相关的关系数据库模式并将修改应用到数据中。运行下面的命令应用现有迁移:
    python manage.py migrate

    你将得到输出包含下面的这行:


    image.png

    你刚刚创建的迁移已经被应用,现在在数据库中存在一个 blog_comment 表。

    接下来,你在管理员站点中添加的你新模型,以通过一个简单的接口去管理评论。打开 blog 应用程序的 admin.py 文件,导入 Comment 模型,并且添加下面的 这个 ModelAdmin 类。

    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')
    

    通过 python manage.py runserver 命令去启动 开发者服务器,并且在你的浏览器中打开: http://127.0.0.1:8000/admin。 你将看到一个新的模型包含在 BLOG 部分。如图下面的屏幕快照:

    image.png

    这个模型现在被注册在 管理员站点中,你可以使用一个简单的接口去 管理 Comment 实例。

    2. 为模型创建表单

    你依然需要构建一个 表单去 让你在 博客帖子中使用评论。记住 Django 有两个基础类去创建表单,FormModelForm。你以前使用了一个去让你可以通过 email 分享 帖子。在这个例子中,你将需要使用 ModelForm,因为你必须在你的 Coment 模型中创建一个动态表单。编辑在你的 blog 应用程序中的 forms.py 文件,并且添加下面这些行:

    from .models import Comment
    
    
    class CommentForm(forms.ModelForm):
        class Meta:
            model = Comment
            fields = ('name', 'email', 'body')
    

    从一个模型中创建一个表单,您只需要在表单的Meta类中指明要使用哪个模型来构建表单。Django 将内省模型并且为你动态的创建表单。

    每个模型字段类型都有相应的默认表单字段类型。定义模型字段的方式将考虑到表单验证。默认情况下,Django 为每一个包含在模型中的字段创建创建一个 表单字段。但是,您可以使用fields列表显式地告诉框架希望在表单中包括哪些字段,或者使用字段的exclude列表定义希望排除哪些字段。为了你的 CommentForm 表单,将使用 name, email, body 字段,因为这些仅仅是用户能填写的字段。

    3. 在视图中处理模型表单

    你将使用 帖子详情 视图去实例化这个表单 并且去处理它。为了保持简单,编辑 views.py 文件,添加导入 Comment 模型 和 CommentForm 表单,并且修改 post_detail 视图,使它看起来像下面这样:

    from .models import Post, Comment
    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()
        return render(request,
                      'blog/post/detail.html',
                      { 'post': post,
                        'comments': comments,
                        'new_comment': new_comment,
                        'comment_form': comment_form})
    

    让我们回顾一下添加到视图中的。你使用这个 post_detail 使用去显示这个 帖子 和 它的评论。你添加了一个 查询集 为这个 帖子 去检索所有有效的评论。 如下:
    comments = post.comments.filter(active=True)

    post 对象去构建这个查询集,而不是直接为 Comment 模型创建一个 查询集。 您可以利用post对象来检索相关的Comment对象。您可以使用管理器对相关对象使用Comment模型中关系的related_name属性定义为comments。您可以使用相同的视图让您的用户添加新的评论。通过将new_comment变量设置为None来初始化它。当一个新的评论被创建的时候使用这个变量。

    如果这个视图通过一个 GET 请求被调用,你将通过 comment_form = CommentForm() 创建一个表单实例。 如果请求是通过 POST 完成的,你将使用从表单中提交的数据去实例化这个表单,并且使用 is_valid() 方法去验证它。如果表单是非法的,你将呈现带有验证错误的表单。如果表单时合法的,你可以采取以下行动:

    1. 你通过调用表单的save() 方法去创建一个新的 Comment 对象,并且将它分配到 new_comment 变量中,如下所示:
      new_comment = comment_form.save(commit=False)

    save()方法创建表单链接的模型实例,并将其保存到数据库中,如果你使用 commit=False 调用它,你创建这模型实例,但是现在不在数据库中保存它。当您希望在最终保存之前修改对象时,这就很方便了,这就是您接下来要做的事情。

    save()方法可用于ModelForm,但不能用于Form实例,因为它们没有链接到任何模型。
    (译者注: ModelForm 里面是包含了一个数据库实例了的,但是 Form 是没有包含的,也就是没有保存到数据库中的)

    1. 您将当前的帖子分配给您刚刚创建的评论:
      new_comment.post = post
      通过做这些,你指定这个新的评论属于这个帖子。

    2. 最后,你通过调用 save() 方法 保存这个新的评论到数据库中。
      new_comment.save()

    您的视图现在可以显示和处理新的评论了。

    4. 在帖子详情模板中添加评论

    你创建函数去为一个帖子管理评论。现在你需要调整 post/detail.html 模板,去做下面这些事情:

    • 为一个帖子显示评论的总数
    • 显示 评论的列表
    • 显示一个表单为用户去添加一个新评论。

    首先,你将添加评论总数。打开post/detail.html 模板并且在 content 快中添加下面代码:

      {% with comments.count as total_comments %}
            <h2>
                {{ total_comments }} comment {{ total_comments|pluralize }}
            </h2>
      {% endwith %}
    

    你可以在 模板中使用 Django 的 ORM,执行查询集的 comments.count() 。注意,Django 模板语言不是使用括号的方式调用方法的。{% with %} 标签允许你为一个新的变量赋值,该变量将一直到 {% endwith %} 标签结束。

    模板标签的{% with %}对于避免多次访问数据库或访问昂贵的方法非常有用。

    你可以使用 pluralize 模板过滤器为 单词 "comment," 根据 total_comments 的值显示一个复数后缀。模板过滤器将其应用于的变量的值作为输入,并返回一个计算过的值。我们将发现在 第三章 扩展博客应用程序 发现更多模板过滤器。

    这个 pluralize 模板过滤器的值不等于1,将返回一个 带有字母 's' 的字符串。前面的文本将被显示为 0 comments, 1 comment, N comments。 Django 有大量的模板标签和过滤器,它们能用来帮助你使用一些方法显示你想要的信息。

    现在让我们来包括评论列表。在 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 }} 变量枚举 评论,它每次迭代包含一个循环计数器。这时你显示发布评论的用户的名字,日期,还有评论的主体。

    最后,你需要程序这个表单或者当它被提交成功后显示一个 成功 消息实例。在前面的代码下面添加下面这些行:

        {% if new_comment %}
            <h2>Your comment has been added.</h2>
        {% else %}
            <h2>Add a new comment</h2>
            <form method="post">
                {{ comment_form.as_p }}
                {% csrf_token %}
                <p><input type="submit" value="Add comment"></p>
            </form>
        {% endif %}
    

    这代码很简单明了,如果 new_comment 对象存在,你显示一个成功的消息,因为评论被成功创建。其他情况下,你通过 一个 段落标签 <p>元素 为每一个字段,以及 作为 POST 请求必须参数的 CSRF token 呈现这个表单。

    在你的浏览器中打开 http://127.0.0.1:8000/blog/ , 并且点击一个 帖子的标题,去得到它的详情页面。你将看到一些像下面快照的东西:

    image.png

    使用表单添加一些评论,它们应该按照时间顺序出现在你的文章下面,如下:


    image.png

    在你的浏览器中打开 http://127.0.0.1:8000/admin/blog/comment/, 你将看到带有被你创建的评论列表的管理员页面。 点击其中它们的一个名字并且编辑它,取消 Active 复选框,并且点击 Save 按钮,你将再次重定向到评论列表,并且 ACTIVE列将为这个评论显示一个 不可用图标。 它看起来像下面快照的第一个评论:

    image.png

    如果你返回到帖子详情视图,你将注意到,这这个不可用评论不再显示了。它也不被计入到评论的总数里面了。感谢这个 active 字段,你可以取消不合法的评论,并且避免在你的帖子中显示它们。

    相关文章

      网友评论

          本文标题:2.2 创建一个评论系统

          本文链接:https://www.haomeiwen.com/subject/iysykktx.html