Django学习之旅(十一)添加博客评论功能

本文为参考追梦人物老师的博客学习记录贴。

本篇为博客开发评论功能,由于功能相对独立,在项目下新建一个应用 comments

新建comments应用

回顾新建应用的过程,在项目路径下,进入cmd界面,使用命令行新建一个项目。

快速进行项目路径下的终端

Django学习之旅(十一)添加博客评论功能

进入虚拟环境

Django学习之旅(十一)添加博客评论功能

新建comments应用

Django学习之旅(十一)添加博客评论功能

创建成功

Django学习之旅(十一)添加博客评论功能

; 一些初始设置

settings.py里注册应用

Django学习之旅(十一)添加博客评论功能

admin后台中 应用的显示名称,在 comments\apps.py 里

from django.apps import AppConfig

class CommentsConfig(AppConfig):
    default_auto_field = 'django.db.models.BigAutoField'
    name = 'comments'
    verbose_name = '评论应用'

Django学习之旅(十一)添加博客评论功能

编写数据模型

创建Comment评论模型。首先需要评论者的一些信息,以及评论时间和评论内容。此外还必须与被评论文章进行关联,知道当前评论属于哪篇文章。

  • *编写模型

进入 comments\models.py

from django.db import models
from django.utils import timezone

class Comment(models.Model):
    name = models.CharField('名字', max_length=50)
    email = models.EmailField('邮箱')
    url = models.URLField('网址', blank=True)
    text = models.TextField('内容')
    created_time = models.DateTimeField('创建时间', default=timezone.now())
    post = models.ForeignKey('blog.Post', verbose_name='文章', on_delete=models.CASCADE)

    class Meta:
        verbose_name = '评论'
        verbose_name_plural = verbose_name

    def __str__(self):
        return '{}:{}'.format(self.name, self.text[:20])

注意:

  1. 所有的模型字段都接受一个 verbose_name的参数,以 第一位置参数或者 "verbose_name="的形式显示指定,表示该字段对外的显示名称。

在admin后台中字段的显示名称:

Django学习之旅(十一)添加博客评论功能

在表单中作为字段的 label值:

Django学习之旅(十一)添加博客评论功能
Django学习之旅(十一)添加博客评论功能
  1. 字段的 default参数表示在新建一个实例时,自动为该字段赋值,只赋一次值;
    而模型的 save()函数同意可以指定字段的保存值。不同之处在于save()函数在每次向数据库保存数据时都生效。
    class Comment(models.Model):
         ...
        created_time = models.DateTimeField('创建时间', default=timezone.now())
        ...

    def save(self, *args, **kwargs):
        ...

        self.modified_time = timezone.now()
        ...

        super().save(*args, **kwargs)
  1. class Meta表示模型的内部类,为模型添加一些功能,或者指定一些标准。如:

指定该模型的数据库表单名字
db_table = ‘axf_wheel’

指定admin后台中 模型的显示名称
verbose_name = ‘评论模型’
verbose_name_plural = verbose_name

Django学习之旅(十一)添加博客评论功能
  1. str()方法,指定查询模型后的返回值。

  2. *模型建立后,进行数据迁移

> python manage.py makemigrations
> python manage.py migrate
  • *将模型注册到admin后台中

comments\admin.py中进行 _comment_模型的注册。

from django.contrib import admin
from comments.models import Comment

class CommentAdmin(admin.ModelAdmin):
    list_display = ['name','email','url','post','created_time']
    fields = ['name','email','url','text','post']

admin.site.register(Comment,CommentAdmin)

模型管理类 CommentAdmin继承自admin.ModelAdmin类。

字段 list_display 表示展示列表中出现的字段。

Django学习之旅(十一)添加博客评论功能

字段 fields 表示编辑页面中需要编辑的字段。

Django学习之旅(十一)添加博客评论功能

django中的表单

表单用于浏览器收集用户信息,并提交到服务器。一般使用POST请求方式。

Django学习之旅(十一)添加博客评论功能
与常规的在HTML页面编辑表单格式不同,django使用 form类进行表单的渲染。

; 创建表单类

  • 继承 forms.Form类或者 forms.ModelForm类生成表单类
from django import forms
from .models import Comment
"""
通过调用这个表单类的一些方法和属性,django 将自动为我们创建常规的表单代码,而不是在html文件中编辑,类似于ORM系统。
"""

"""
那么怎么展现一个表单呢?django 会根据表单类的定义自动生成表单的 HTML 代码,
我们要做的就是实例化这个表单类,然后将表单的实例传给模板,让 django 的模板引擎来渲染这个表单。
"""
class CommentForm(forms.ModelForm):

    class Meta:
        model = Comment
        fields = ['name', 'email', 'url', 'text']
  • 首先导入基类forms,其下有两个派生类 forms.ModelFormforms.Form。其中forms.ModelForm表单有对应的数据模型,而forms.Form表单可以没有对应的数据模型。
  • 在元类class Meta中,指定表单对接的数据模型,以及表单需要收集的字段。
  • 在django中表单的创建原理:系统根据 表单类的定义自动生成表单的 HTML 代码,我们要做的就是实例化这个表单类,然后将表单实例传给模板,然后django 的模板引擎会自动渲染这个表单。

使用表单类

有了表单类CommentForm后,接下来要做的就是实例化一个表单类对象,然后将其传递到前端。在前端使用到这个表单类的地方就会自动渲染为一个表单。

Django学习之旅(十一)添加博客评论功能
Django学习之旅(十一)添加博客评论功能

在本文中我们使用 自定义模板标签来渲染一个局部的 HTML评论 页面。
; 创建用于评论展示的模板标签

  • *模板标签函数

创建标签函数的python

Django学习之旅(十一)添加博客评论功能

注册模板标签函数
标签函数使用post对象、form表单对象作为参数,如果表单对象为空则实例化一个对象。如果存在则直接传递给模板。

comments\templatetags\comment_extras.py

from django import template

from comments.forms import CommentForm

register = template.Library()

@register.inclusion_tag(r'comment\inclusions\_form.html',takes_context=True)
def show_comments_form(context, post, form=None):
   if form is None:
       form = CommentForm()

   return {
       'form': form,
       'post': post,
   }
  • *渲染标签模板

创建标签模板进行渲染

Django学习之旅(十一)添加博客评论功能
templates\comment\inclusions\_form.html

<form action="{% url 'comments:comment' post.pk  %}" method="post">
    {% csrf_token %}
    <div class="row">
    <div class="col-md-4">
        <label for="{{ form.name.id_for_label }}">{{form.name.label}}:</label>
        {{form.name}}
        {{form.name.errors}}
    </div>
    <div class="col-md-4">
        <label for="{{form.email.id_for_label}}">{{form.email.label}}:</label>
        {{form.email}}
        {{form.email.errors}}
    </div>
    <div class="col-md-4">
        <label for="{{form.url.id_for_label}}">{{form.url.label}}:</label>
        {{form.url}}
        {{form.url.errors}}
    </div>
    <div class="col-md-10">
        <label for="{{form.text.id_for_label}}">{{form.text.label}}:</label>
        {{form.text}}
        {{form.text.errors}}
        <button type="submit" class="comment-btn">发表</button>
    </div>
        </div>
</form>

注意:
<form>&#x8868;&#x5355;</form>
创建表单标签,向url提交用户信息。
action: 提交的url
method: 请求方式
csrf_token
CSRF 令牌,用于防护跨站请求攻击(CSRF)
<label></label>标签
label 标签为某个表单元素定义标注(标签),提高用户体验
作用:
用于绑定一个表单元素, 当点击label标签的时候, 被绑定的表单元素就会获得输入焦点。当我们鼠标点击 label标签里面的文字时, 光标会定位到指定的表单里面。

Django学习之旅(十一)添加博客评论功能
增加label标签后,点击文本框可以选中,点击框前的文字”姓名”也可以选择进行输入。
使用:
用for 属性与表单的id关联,用于规定 label 与哪个表单元素绑定。
<label for="name1">姓名</label>
<input type="text" name="name"  id="name1">

{{form.name.label}}
表单字段的显示名,根据表单对应的模型的字段的verbose_name属性进行提取。
{{form.name}}
表单字段,在模板中自动渲染成表单html代码
{{form.name.errors}}
表单填写过程中的错误自动保存到了 errors中,在模板中会自动将错误渲染并展示出来。

  • *使用模板标签进行评论表单的展示
templates\blog\detail.html

{% load  comment_extras %}
    ...

<div class="comment-list-panel">
    {% show_comments post %}
</div>
    ...

在当前页面,我们传递了post对象,而没有form对象,因此表单内容为空,会实例化一个空白表单对象并展示。

Django学习之旅(十一)添加博客评论功能

处理表单数据的视图函数

  • 首先获取评论针对的文章
  • 然后通过request.POST请求获取表单数据并封装到表单对象中
  • 检验表单数据的合法性
  • 将表单数据封装为模型数据,保存到数据库中
  • 表单数据不合法则渲染一个修改页面,重新提交
from django.contrib import messages
from django.shortcuts import render, redirect
from blog.models import Post
from django.shortcuts import get_object_or_404
from .forms import CommentForm

def comment(request, pk):
    post = get_object_or_404(Post,pk=pk)
    form = CommentForm(request.POST)

    if form.is_valid():
        comment = form.save(commit=False)
        comment.post = post
        comment.save()

        messages.add_message(request, messages.SUCCESS,'评论发表成功!',extra_tags='success')
        return redirect(post)

    messages.add_message(request,messages.ERROR,'评论失败!请修改表单中的错误后再重新提交。', extra_tags='danger')
    context = {
        'post': post,
        'form': form,
    }
    return render(request, r'comment\preview.html', context=context)

数据的层层传递
form = CommentForm(request.POST) — 将POST的请求数据包装成表单对象
comment = form.save(commit=False) — 将表单对象包装成数据模型
comment.save() —将模型数据保存到数据库中

数据的层层传递需要 &#x5B57;&#x6BB5; 始终保持一致性

Django学习之旅(十一)添加博客评论功能

messages.add_message(request, messages.SUCCESS,'&#x8BC4;&#x8BBA;&#x53D1;&#x8868;&#x6210;&#x529F;&#xFF01;',extra_tags='success')
添加全局上下文消息,第一个参数为请求,第二个参数为消息等级,第三个参数为消息内容,第四个参数为额外标签,用于HTML 标签的 class 属性,增加样式。
消息messages作为全局变量,可以在模板的任何位置进行获取(如果进行了赋值)

在详情页面进行消息提醒:

<header>
  ...

</header>
{% if messages %}
    {% for message in messages %}
      <div class="alert alert-{{ message.tags }} alert-dismissible" role="alert">
        <button type="button" class="close" data-dismiss="alert" aria-label="Close"><span
                aria-hidden="true">&times;</span></button>
        {{ message }}
      </div>
    {% endfor %}
{% endif %}

url的设置

comment应用下的url绑定

comments\urls.py

from django.urls import path
from . import views

app_name = 'comments'

urlpatterns = [
    path('comment/', views.comment, name='comment')
]

在项目目录下进行注册

django1\urls.py

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('blog.urls')),
    path('',include('comments.urls'))
]

显示评论内容

同样使用模板标签进行局部页面渲染,展示评论内容。
首先编写标签函数:

comments\templatetags\comment_extras.py

@register.inclusion_tag(r'comment\inclusions\_comment.html',takes_context=True)
def show_comments(context, post):
    comment_list = post.comment_set.all().order_by('-created_time')
    comment_count = comment_list.count()
    return {
        'comment_list':comment_list,
        'comment_count': comment_count,
    }

通过传入的post对象筛选关联的评论,即comment数据。然后将评论列表传递给标签模板中进行渲染。
注意:
post.comment_set.all()表示筛选与post关联的所有comment对象。以post出发,寻找与其关联的多个comment,all()方法返回找到的所有comment对象。适用于有 &#x5916;&#x952E;&#x5173;&#x8054;的两个模型, &#x7531;&#x4E00;&#x627E;&#x591A;

标签模板中的渲染

 <h3>评论列表,共<span>{{comment_count}}</span>条评论</h3>
<ul class="comment-list list-unstyled">
    {% for comment in comment_list %}
    <li class="comment-item">
       <span class="nickname">
           {{comment.name}}
       </span>
        <time class="submit-date" datetime="{{comment.created_time}}">
            {{comment.created_time}}
        </time>
        <div class="text">
            {{comment.text|linebreaks}}
        </div>
    </li>
    {% empty %}
    暂无评论
    {% endfor %}
</ul>

其中{{comment.text|linebreaks}}中的 linebreaks表示换行过滤器。

使用模板标签:

<div class="comment-list-panel">
   {% show_comments post %}
</div>

一些其他的完善点

在模型中指定排序:
对于需要经常排序输出的模型数据,我们可以在 models.Model 的子类里定义一个名为 Meta 的内部类,通过这个内部类指定一些属性的值来规定这个模型类该有的一些特性,例如在这里我们要指定 Post 的排序方式。首先看到 Post 的代码,在 Post 模型的内部定义的 Meta 类中,指定排序属性 ordering:

class Post(models.Model):
   ...

    class Meta:
        verbose_name = '文章'
        verbose_name_plural = '文章'
        ordering = ['-created_time']
   ...

这样Post模型的输出就总是按创建时间进行排序输出了。

跳转到页面指定区域:
通过url链接不但可以跳转到指定页面,还可以通过 #id&#x503C;的方式跳转到指定页面的指定区域

如想要跳转到详情页面的评论区域,评论区的id值为 id="comment-area"

<section class="comment-area" id="comment-area">
                    <hr>
                    <h3>发表评论</h3>
                    {% show_comments_form post %}
                    <div class="comment-list-panel">
                        {% show_comments post %}
                    </div>
                </section>

则跳转链接为 href="{{post.get_absolute_url}}#comment-area"

Original: https://blog.csdn.net/weixin_37881839/article/details/125440486
Author: 气概
Title: Django学习之旅(十一)添加博客评论功能

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/737716/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 【DKN】(三)data_preprogress.py

    注入产生的原理: 数据库设置为GBK编码: 宽字节注入源于程序员设置MySQL连接时错误配置为:set character_set_client=gbk,这样配置会引发编码转换从而…

    Python 2022年12月31日
    0124
  • 30张炫酷的动态交互式图表,Python 一键即可生成

    注入产生的原理: 数据库设置为GBK编码: 宽字节注入源于程序员设置MySQL连接时错误配置为:set character_set_client=gbk,这样配置会引发编码转换从而…

    Python 2023年1月9日
    066
  • pytest初级使用

    注入产生的原理: 数据库设置为GBK编码: 宽字节注入源于程序员设置MySQL连接时错误配置为:set character_set_client=gbk,这样配置会引发编码转换从而…

    Python 2023年1月19日
    075
  • Pygame:外星人入侵

    注入产生的原理: 数据库设置为GBK编码: 宽字节注入源于程序员设置MySQL连接时错误配置为:set character_set_client=gbk,这样配置会引发编码转换从而…

    Python 2023年1月20日
    0100
  • miniconda3介绍、安装、使用教程

    简单来说conda有什么用? 方便的创建多个python虚拟环境,方便多个python项目同时开发的时候,每个项目都有自己独立的python开发环境。 相当于在一个园区,建立很多仓…

    Python 2023年8月1日
    039
  • Cora 数据集介绍

    数据集包含以下文件: ind.cora.x : 训练集节点特征向量,保存对象为:scipy.sparse.csr.csr_matrix,实际展开后大小为: (140, 1433) …

    Python 2023年10月26日
    027
  • Python游戏开发,pygame模块,Python实现打砖块小游戏

    注入产生的原理: 数据库设置为GBK编码: 宽字节注入源于程序员设置MySQL连接时错误配置为:set character_set_client=gbk,这样配置会引发编码转换从而…

    Python 2023年1月22日
    065
  • 【笔试强训】Day 7

    注入产生的原理: 数据库设置为GBK编码: 宽字节注入源于程序员设置MySQL连接时错误配置为:set character_set_client=gbk,这样配置会引发编码转换从而…

    Python 2023年1月24日
    072
  • git相关问题解析,你想要的都有🔥

    注入产生的原理: 数据库设置为GBK编码: 宽字节注入源于程序员设置MySQL连接时错误配置为:set character_set_client=gbk,这样配置会引发编码转换从而…

    Python 2023年1月28日
    081
  • pandas基础_1

    数据使用泰坦尼克数据 基本操作 读取训练集数据 df = pd.read_csv(‘train.csv’) 常用的基本信息查询 df.head() #&#x9ED8;&am…

    Python 2023年8月7日
    026
  • Python学习笔记: pip install 常见错误汇总

    本机环境RHEL8, Python3.9 在pypi上查看pkg的页面,因为有些pip包的版本对特定的python版本有要求 src/kerberos.c:18:10: fatal…

    Python 2023年6月10日
    078
  • 不同维度矩阵相乘

    注入产生的原理: 数据库设置为GBK编码: 宽字节注入源于程序员设置MySQL连接时错误配置为:set character_set_client=gbk,这样配置会引发编码转换从而…

    Python 2023年1月11日
    0149
  • Python类的定义和使用

    Python类的定义和使用 一、前言 二、定义类 三、创建类的实例 四、”魔术”方法—— init () 五、创建类的成员并访问 * 1.创建实例方法并访问…

    Python 2023年7月31日
    053
  • [转]深刻理解Python中的元类(metaclass)以及元类实现单例模式

    注入产生的原理: 数据库设置为GBK编码: 宽字节注入源于程序员设置MySQL连接时错误配置为:set character_set_client=gbk,这样配置会引发编码转换从而…

    Python 2022年8月14日
    0170
  • Python requests 爬取淘宝商品数据,并连接数据库,保存数据

    注入产生的原理: 数据库设置为GBK编码: 宽字节注入源于程序员设置MySQL连接时错误配置为:set character_set_client=gbk,这样配置会引发编码转换从而…

    Python 2023年2月6日
    075
  • 【pytest-fixture】九、fixture的参数化

    注入产生的原理: 数据库设置为GBK编码: 宽字节注入源于程序员设置MySQL连接时错误配置为:set character_set_client=gbk,这样配置会引发编码转换从而…

    Python 2023年1月18日
    072
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球