IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> Django学习之旅(十一)添加博客评论功能 -> 正文阅读

[Python知识库]Django学习之旅(十一)添加博客评论功能

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

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

新建comments应用

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

快速进行项目路径下的终端
在这里插入图片描述

进入虚拟环境
在这里插入图片描述

新建comments应用
在这里插入图片描述

创建成功
在这里插入图片描述

一些初始设置

settings.py里注册应用
在这里插入图片描述

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

from django.apps import AppConfig

class CommentsConfig(AppConfig):
    default_auto_field = 'django.db.models.BigAutoField'
    name = 'comments'
    verbose_name = '评论应用'   # 在admin后台的显示名

在这里插入图片描述

编写数据模型

创建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())  # default:创建时添加  save函数:保存到数据库时添加
    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后台中字段的显示名称:
在这里插入图片描述>

在表单中作为字段的label值:
在这里插入图片描述
在这里插入图片描述

  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
在这里插入图片描述

  1. str()方法,指定查询模型后的返回值。
  • 模型建立后,进行数据迁移

> 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 表示展示列表中出现的字段。
在这里插入图片描述

字段fields 表示编辑页面中需要编辑的字段。
在这里插入图片描述

django中的表单

表单用于浏览器收集用户信息,并提交到服务器。一般使用POST请求方式。
在这里插入图片描述
与常规的在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):
    # 表单类,继承自forms
    # forms.ModelForm表单有对应的数据模型
    # forms.Form表单可以没有对应的数据模型

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

使用表单类

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

在这里插入图片描述
在这里插入图片描述

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

创建用于评论展示的模板标签

  • 模板标签函数

创建标签函数的python包
在这里插入图片描述

注册模板标签函数
标签函数使用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,
   }
  • 渲染标签模板

创建标签模板进行渲染
在这里插入图片描述

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>表单
创建表单标签,向url提交用户信息。
action: 提交的url
method: 请求方式
csrf_token
CSRF 令牌,用于防护跨站请求攻击(CSRF)
<label>标签
label 标签为某个表单元素定义标注(标签),提高用户体验
作用:
用于绑定一个表单元素, 当点击label标签的时候, 被绑定的表单元素就会获得输入焦点。当我们鼠标点击 label标签里面的文字时, 光标会定位到指定的表单里面。
在这里插入图片描述
增加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对象,因此表单内容为空,会实例化一个空白表单对象并展示。

表单显示成功在这里插入图片描述

处理表单数据的视图函数

  • 首先获取评论针对的文章
  • 然后通过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

# Create your views here.
def comment(request, pk):
    post = get_object_or_404(Post,pk=pk)  # 根据pk查找post对象
    form = CommentForm(request.POST)  # 通过提交的POST数据生成表单对象

    if form.is_valid():
        comment = form.save(commit=False)   # 表单对象的save方法将生成对应的模型实例,commit表示是否将模型数据保存数据库
        comment.post = post   # 提交的POST数据中并没有post的数据
        comment.save()   # 最后保存到数据库

        # 消息被缓存在 cookie 中,然后我们在模板中获取显示即可。
        messages.add_message(request, messages.SUCCESS,'评论发表成功!',extra_tags='success')
        return redirect(post)  # 重定向一个模型时,将调用这个模型的get_absolute_url 方法
    # 如果没有重定向,说明表单有误,则渲染一个错误页面,展示错误详情
    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() —将模型数据保存到数据库中

数据的层层传递需要字段始终保持一致性
在这里插入图片描述在这里插入图片描述在这里插入图片描述

messages.add_message(request, messages.SUCCESS,'评论发表成功!',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'  # 告诉程序,当前的url模块属于哪个应用  ---  试图函数命名空间

urlpatterns = [
    path('comment/<int:pk>', 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对象。适用于有外键关联的两个模型,由一找多

标签模板中的渲染

 <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值的方式跳转到指定页面的指定区域

如想要跳转到详情页面的评论区域,评论区的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"

  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2022-07-04 22:49:56  更:2022-07-04 22:52:39 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/27 2:48:12-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计