Django大回顾-4 自定义过滤器和标签、模型层

【1】自定义过滤器,自定义标签

第一步

首先注册一个app

第二步

在注册的app下创建一个包,包名必须为templatetags

第三步

在templatetags包下面创建一个py文件,文件名随便起

第四步

在py文件中写入:以下代码

python 复制代码
from django import template

from django.utils.safestring import mark_safe

register = template.Library()      # register的名字是固定的,不可改变



定义自己的过滤器或标签

'''

定义过滤器使用:@register.filter

定义标签使用:@register.simple_tag

'''


# 定义一个过滤器,实现敏感词替换功能

@register.filter
def filter_words(content:str)->str:
    l = ['妈的', '傻逼', '退游']
    # 把content中所有关键词,替换,返回
    for item in l:
        content = content.replace(item, "**")
    return content




# 定义一个标签

@register.simple_tag
def my_input(id,arg):
    result = "<input type='text' id='%s' class='%s' />" %(id,arg)
    return mark_safe(result)

第五步

在模板上使用

html 复制代码
//导入过滤器
{% load comm_filter %}

//过滤器使用

{{ content|filter_words }}

//标签使用

{% my_input 7 'red' %}

二、模型层(models.py)

【1】orm框架 ------ 对象映射关系

数据库 Django程序中

数据表 --------映射----------》类

记录 ----------映射-----------》对象

【2】利用Django创建一张表

python 复制代码
from django.db import models

# 写一个个类​
class Book(models.Model):    

    id = models.AutoField(primary_key=True)    

    title = models.CharField(max_length=64, null=False)
    
    price = models.DecimalField(max_digits=7, decimal_places=2)       



'''
注意:
    1、类必须继承models.Model
    
    2、写好类后,必须执行数据库迁移
    
    3、数据库迁移命令:
        manage.py makemigrationspython    ------ 生成迁移记录(先执行)
        
        manage.py migrate  --------- 将数据写入到数据库中(后执行)

'''

【3】常用字段和非常用字段

|------------------------------------------------------------------------|--------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 字段名 | 解释和传参 | 注意 |
| AutoField(Field) | int自增列,必须填入参数 primary_key=True | 当model中如果没有自增列,则自动会创建一个列名为id的列 |
| BigAutoField(AutoField) | bigint自增列,必须填入参数 primary_key=True | |
| SmallIntegerField(IntegerField): | 小整数 -32768 ~ 32767 | |
| PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField) | 正小整数 0 ~ 32767 | |
| IntegerField(Field) | 整数列(有符号的) -2147483648 ~ 2147483647 | |
| PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField) | 正整数 0 ~ 2147483647 | |
| BigIntegerField(IntegerField): | 长整型(有符号的) -9223372036854775808 ~ 9223372036854775807 | |
| BooleanField(Field) | 布尔值类型 | |
| NullBooleanField(Field): | 可以为空的布尔值 | |
| CharField(Field) | 字符类型 | 必须提供max_length参数, max_length表示字符长度 |
| TextField(Field) | 文本类型 | |
| EmailField(CharField): | 字符串类型,Django Admin以及ModelForm中提供验证机制 | |
| IPAddressField(Field) | 字符串类型,Django Admin以及ModelForm中提供验证 IPV4 机制 | |
| URLField(CharField) | URLField(CharField) | |
| SlugField(CharField) | 字符串类型,Django Admin以及ModelForm中提供验证支持 字母、数字、下划线、连接符(减号) | |
| CommaSeparatedIntegerField(CharField) | 字符串类型,格式必须为逗号分割的数字 | |
| UUIDField(Field) | 字符串类型,Django Admin以及ModelForm中提供对UUID格式的验证 | |
| FilePathField(Field) | 字符串,Django Admin以及ModelForm中提供读取文件夹下文件的功能 | 参数: path, 文件夹路径 match=None, 正则匹配 recursive=False, 递归下面的文件夹 allow_files=True, 允许文件 allow_folders=False, 允许文件夹 |
| FileField(Field) | 字符串,路径保存在数据库,文件上传到指定目录 | 参数: upload_to = "" 上传文件的保存路径 storage = None 存储组件,默认django.core.files.storage.FileSystemStorage |
| ImageField(FileField) | 字符串,路径保存在数据库,文件上传到指定目录 | 参数: upload_to = "" 上传文件的保存路径 storage = None 存储组件,默认django.core.files.storage.FileSystemStorage width_field=None, 上传图片的高度保存的数据库字段名(字符串) height_field=None 上传图片的宽度保存的数据库字段名(字符串) |
| DateTimeField(DateField) | 日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] | |
| DateField(DateTimeCheckMixin, Field) | 日期格式 YYYY-MM-DD | |
| TimeField(DateTimeCheckMixin, Field) | 时间格式 HH:MM[:ss[.uuuuuu]] | |
| DurationField(Field) | 长整数,时间间隔,数据库中按照bigint存储,ORM中获取的值为datetime.timedelta类型 | |
| FloatField(Field) | 浮点型 | |
| DecimalField(Field) | 10进制小数 - 参数: max_digits,小数总长度 decimal_places,小数位长度 | |
| BinaryField(Field) | 二进制类型 | |

【4】常用非常用字段参数

|-------------|--------------------------------------------------------------------------------------------------------------------------------------------------------|
| 字段参数 | 解释 |
| null | 如果为True,Django 将用NULL 来在数据库中存储空值。 默认值是 False. |
| blank | 后台管理---》admin中会用。 如果为True,该字段允许不填。默认为False。 要注意,这与 null 不同。null纯粹是数据库范畴的,而 blank 是数据验证范畴的。 如果一个字段的blank=True,表单的验证将允许该字段是空值。如果字段的blank=False,该字段就是必填的。 |
| default | 字段的默认值。可以是一个值或者可调用对象。如果可调用 ,每有新对象被创建它都会被调用 |
| primary_key | 如果为True,那么这个字段就是模型的主键。如果你没有指定任何一个字段的primary_key=True, Django 就会自动添加一个IntegerField字段做为主键,所以除非你想覆盖默认的主键行为, 否则没必要设置任何一个字段的primary_key=True。 |
| unique | 如果该值设置为 True, 这个数据字段的值在整张表中必须是唯一的 |
| db_index | 该字段建立索引 |
| choices | 由二元组组成的一个可迭代对象(例如,列表或元组),用来给字段提供选择项。 如果设置了choices ,默认的表单将是一个选择框而不是标准的文本框,<br>而且这个选择框的选项就是choices 中的选项。 get_type_book_display() |

【4.1】关于Meta

python 复制代码
class UserInfo(models.Model):
       nid = models.AutoField(primary_key=True,index=True)
       username = models.CharField(max_length=32)
       mobile=models.CharField(max_length=32)
       class Meta:
           # 数据库中生成的表名称 默认 app名称 + 下划线 + 类名
           db_table = "table_name"

           # 联合索引
           index_together = [
               ("username", "mobile"),
           ]

           # 联合唯一索引
           unique_together = (("username", "mobile"),)

           # admin中显示的表名称
           verbose_name='图书表'

           # verbose_name加s
           verbose_name_plural

【5】在settings.py中配置mysql

可以使用Django自带的sqlite,也可以在settings.py文件中的DATABASE中配置自己的mysql

python 复制代码
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'day05',
        'HOST':'127.0.0.1',
        'PORT':3306,
        'USER':'root',
        'PASSWORD':'1234',
    }
}

配置完自己的mysql,项目默认会启动不了,需要在创建的应用的__init__.py文件或项目自带的__init__.py文件中导入pymysql模块或mysqlclient模块

1、导入pymysql模块

python 复制代码
import pymysql

pymysql.install_as_MySQLdb()

2、导入mysqlclient模块

python 复制代码
import mysqlclient

【6】基本操作(增、删、改、查)

【6.1】增加删除字段

增加删除字段,只需要在表模型,增加,注释字段,增加删除字段参数,再迁移就可以了

-不要轻易删除迁移记录

【6.2】增加表记录

方案一:

python 复制代码
Book.objects.create(参数)

方案二:

python 复制代码
book=Book(参数)
book.save()

【6.3】删除记录

方式一:查出来再删

python 复制代码
Book.objects.all().delete()

方式二:

python 复制代码
#可以重写类中得delete方法
    	book=Book.objects.filter(pk=1).first()
        book.delete() #Book 类中有个delete方法,咱们没有写---》父类的--》可以重写

【6.4】修改记录

方式一:查出来再修改

python 复制代码
Book.objects.all().update(参数)

方式二:

python 复制代码
book=Book.objects.filter(pk=1).first()
        book.name='ss'
        book.save()

【6.5】13中查询方法

|----------------------|----------------------------------------------------------------------------------------|
| 方法 | 解释 |
| all() | 查询所有结果 |
| filter(**kwargs) | 它包含了与所给筛选条件相匹配的对象 - ------- 过滤,没有查到,会返回None |
| get(**kwargs) | 返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误。 |
| exclude(**kwargs) | 它包含了与所给筛选条件不匹配的对象 --------- 排除 |
| order_by(*field) | 对查询结果排序('-id') ---- 默认升序排 |
| reverse() | 对查询结果反向排序 |
| count() | 返回数据库中匹配查询(QuerySet)的对象数量。 ------ 返回个数 |
| first() | 返回第一条记录 |
| last() | 返回最后一条记录 |
| exists() | 如果QuerySet包含数据,就返回True,否则返回False |
| values(*field) | 返回一个ValueQuerySet------一个特殊的QuerySet,运行后得到的并不是一系列model的实例化对象,而是一个可迭代的字典序列 ---- 返回列表套字典 |
| values_list(*field) | 它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列 ---------- 返回的是列表套元组 |
| distinct() | 从返回结果中剔除重复纪录 - --------- 去重 |

【6.6】创建表关系

关联表关系有如下几种

1、一对一:本质就是一对多,只不过多的字段唯一

2、一对多:外键关联

3、多对多:必须要有中间表

python 复制代码
class Book(models.Model):
    name = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=5, decimal_places=2)
    publish_date = models.DateField()
    publish = models.ForeignKey(to='Publish',on_delete=models.CASCADE)
    #这不是个字段
    authors=models.ManyToManyField(to='Author')
    def __str__(self):
        return self.name


class Author(models.Model):
    name = models.CharField(max_length=32)
    age = models.IntegerField()
    author_detail = models.OneToOneField(to='AuthorDatail',unique=True,on_delete=models.CASCADE)

class AuthorDatail(models.Model):
    telephone = models.BigIntegerField()
    birthday = models.DateField()
    addr = models.CharField(max_length=64)

class Publish(models.Model):
    name = models.CharField(max_length=32)
    city = models.CharField(max_length=32)
    email = models.EmailField()

【6.7】on_delete的可选参数

|---------------------|------------------------------------------------------------------------------|
| 参数 | 解释 |
| models.CASCADE | 级联删除---》删除出版社---》当前出版社下所有的图书数据都会被删除 |
| models.SET_NULL | 删除出版社---》当前出版社下所有的图书数据都会的publish_id字段都是置为空,必须加参数null=True |
| models.SET_DEFAULT | 删除出版社---》当前出版社下所有的图书数据都会的publish_id字段都设为默认值,必须加默认值(default),例如:default=1 |
| models.SET(值/可调用对象) | 当前出版社下所有的图书数据都会的publish_id字段都设为SET传入的值,如果是可调用对象,会执行可调用对象,把return的值返回过来 |
| models.DO_NOTHING | 删除出版社---》当前出版社下所有的图书数据都会的publish_id字段 原封不动,必须加 db_constraint=False 这个参数 |

【6.8】正反向概念

正向:

拥有外键字段的表去查别的表,就是正向

正向查询使用 ---------- 外键字段查,如果有多条直接加上all()

反向:

没有外键字段的表查有外键字段的表 ,就是反向查询

反向查询使用 ---------- 表名小写查,如果查询的结果有多条需加上_set.all()

关于什么时候加all()问题:

1、一对一表关系 ---------------- 不用加all()

2、一对多表关系:

例如:出版社表查图书表 ------ 正向 ------- 直接用all()

图书表查出版社 -------- 反向 ------- 不用加all()

3、多对多表关系:

1、无论是正向查询还是反向查询,都需要加上all()

2、正向 ----------》 直接加上.all()

3、反向 ----------》 加上_set.all()

【6.9】基于对象的跨表查询(子查询)

python 复制代码
 ### 一对一正反向

    # 正向:
    # author = Author.objects.all().first()
    # print(author.author_detail.addr)

    # 反向
    # author_detail=AuthorDatail.objects.filter(pk=3).first()
    # print(author_detail.author.name)


    # 一对多
    # 正向:
    # book=Book.objects.all().first()
    # print(book.publish.name)

    # 反向
    # publish=Publish.objects.filter(pk=2).first()
    # print(publish.book_set.all())


    # 多对多
    # 正
    # book=Book.objects.filter(pk=3).first()
    # book=Book.objects.filter(pk=2).first()
    # print(book.authors.all())

    # 反
    # author=Author.objects.all().first()
    # print(author.book_set.all())

【6.10】基于双下划线的联表查询

python 复制代码
  ### 通过 __ 链表
    #
    ###  一对一链表- 正反向
    # 拿出id为1的作者(作者表)   的地址(作者详情表)
    # 正向---》字段名 author_detail
    # res=Author.objects.filter(pk=1).values('id','name','age','author_detail__addr')
    # print(res)

    # 反向---》查询 作者地址是 北京 的作者名和作者年龄
    # 反向--》表名小写
    # res=AuthorDatail.objects.filter(addr='北京').values('addr','author__name','author__age')
    # print(res)


    ### 一对多正反向
    # 查询北京出版社出版过的所有书籍的名字与价格(一对多)
    # 反 :表名小写
    # res=Publish.objects.filter(name='北京出版社').values('name','book__name','book__price')
    # print(res)
    # 正: 按字段
    # res=Book.objects.filter(publish__name='北京出版社').values('publish__name','name','price')
    # print(res)



    ## 多对多关系
    #练习: 查询张三出过的所有书籍的名字(多对多)
    # 反
    res=Author.objects.filter(name='张三').values("name","book__name")
    # print(res)

    # 正
    res=Book.objects.filter(authors__name='张三').values('authors__name','name')
    # print(res)

    #### # 查询红楼梦这本书出版社的名字####


    # 查询北京出版社出版过的所有书籍的名字以及作者的姓名
    # res=Publish.objects.filter(name='北京出版社').values('book__name','book__authors__name','book__authors__author_detail__addr')
    # print(res)

    res=Book.objects.filter(publish__name='北京出版社').values('name','authors__name')
    # print(res)

    res = Author.objects.filter(book__publish__name='北京出版社').values('book__name','name')
    print(res)
相关推荐
Elastic 中国社区官方博客6 分钟前
Elasticsearch:Workflows 介绍 - 9.3
大数据·数据库·人工智能·elasticsearch·ai·全文检索
B站_计算机毕业设计之家8 分钟前
豆瓣电影推荐系统 | Python Django Echarts构建个性化影视推荐平台 大数据 毕业设计源码 (建议收藏)✅
大数据·python·机器学习·django·毕业设计·echarts·推荐算法
仍然.10 分钟前
MYSQL--- 聚合查询,分组查询和联合查询
数据库
一 乐14 分钟前
校园二手交易|基于springboot + vue校园二手交易系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端
啦啦啦_999916 分钟前
Redis-0-业务逻辑
数据库·redis·缓存
自不量力的A同学1 小时前
Redisson 4.2.0 发布,官方推荐的 Redis 客户端
数据库·redis·缓存
Exquisite.1 小时前
Mysql
数据库·mysql
全栈前端老曹1 小时前
【MongoDB】深入研究副本集与高可用性——Replica Set 架构、故障转移、读写分离
前端·javascript·数据库·mongodb·架构·nosql·副本集
R1nG8631 小时前
CANN资源泄漏检测工具源码深度解读 实战设备内存泄漏排查
数据库·算法·cann
阿钱真强道2 小时前
12 JetLinks MQTT直连设备事件上报实战(继电器场景)
linux·服务器·网络·数据库·网络协议