Bootstrap

第十章:django模型类(二)

 系列文章目录

第一章 :Django安装与配置虚拟环境

第二章:django各模块的作用以及参数说明

第三章:  Django的路由与视图

第四章:django请求

第五章:django会话

第六章:django中的cookie与session

第七章:视图类

第八章:模型类

第九章:django与mysql连接与迁移

文章目录

一、定义模型类

1.定义

2.生成迁移文件

3.同步数据库

二.测试模型类

1.增

方式一:

方式二:

2.查

基本查询

过滤查询

3.删

方法一:

方法二:

4.改

方法一:

方法二:

5.进阶

F对象:

Q对象:

聚合函数

排序

关联查询

三.补充

1.查询集

2.两大特性

惰性执行

缓存

3.管理器(Manager)

总结


前言

学习模型类之前首先要了解的是orm(Object Relational Mapping)框架,在django中内嵌了orm框架,简单来讲,orm框架帮我们把数据库中的数据表映射成一个对象,并且还能帮我们自动创建数据表,省去了我们创建表的过程。在我们想要对数据库中的数据进行操作时,只需要对相应的对象进行相关的操作即可,剩下的orm会帮我们完成。在第九章中简单介绍了下django的数据库的简单操作,在本章,进行深入的了解。

一、定义模型类

注意:

  • 模型类必须继承from django.db import models下的Model
  • 模型类必须卸载models.py中

1.定义

class PeopleInfo(models.Model):
    name = models.CharField(verbose_name='人名', max_length=20)
    book = models.ForeignKey(BookInfo, on_delete=models.PROTECT, verbose_name='外键')
    jianjie = models.CharField(verbose_name='简介', max_length=200, null=True)
    is_del = models.BooleanField(verbose_name='是否可用', default=False)
    choices = ((0, 'nan'), (1, 'nv'))
    sex = models.SmallIntegerField(verbose_name='性别', choices=choices,null=True)

    class Meta:
        # 指定表名
        db_table = 'Peopleinfo'
        # 在admin后台显示名称
        verbose_name = '人物'
        # 在后台显示名称不加复数
        verbose_name_plural = verbose_name

    def __str__(self):
        # 当直接调用对象是返回该对象的name字段的数据
        return self.name

主键:如果没有手动指定,django会自动创建一个主键字段id

常用字段类型与参数表

常用字段类型
数值型
AutoField  int(11)自动增长主键,没有指定时由django自动创建primary_key=True(是否作为主键)
BooleanField  tinyint(1)布尔类型
DecimalFielddecimal定点型数据,max_digits=8(最大长度,整数加小数)decimal_places=2(精度,小数点后)
IntegerField  int(11)整型
PositiveIntegerFieldint(11)正整数
SmallIntegerFieldsmallint小整数
字符型
CharField varchar  字符型
URLField  varchar  继承自字符型,实现对url的特殊处理
UUIDField  char(32)存放固定长度的id
EmailField  varchar  继承自字符型,实现对Email的特殊处理
FileField  varchar  继承自字符型,实现对file的特殊处理
TextField   longtext文本类型,存放大量数据
ImageField  varchar  

继承自字符型,实现对image的特殊处理

日期类型
dateFielddata日期类型
DateTimeFielddatatime日期时间类型
TimeField time时间类型
关系类型

on_delete参数表示在主表数据删除时执行的操作

CASCADE 级联,主删->从删

PROTECT 保护,主删->从拦

SET_NULL 主删->从变空

SET_DEFAULT 主删->从变默认值

SET() 自定义方法

ForeignKey

作为一对多的外键使用

OneToOneField

作为一对一的外键使用(一对多的情况下限制了外键唯一)

ManyToManyField

作为多对多的外键使用,会创建中间表
常用参数
null  true,false数据库层面是否可以为空
blank  true,false业务层面是否可以为空
choices  ((数据,注释),(数据,注释),)在admin界面可以看到选项
db_column  这个参数可以指定Model中的某个字段对应数据库中的哪个字段
db_index  索引配置对于业务上需要进行作为查询条件的字段,应该配置此项
default  默认值
editable  true,false是否可编辑
error_messages  {‘’:‘’}字段校验失败的提示
help_text  提示语句
primary_keytrue,false设置主键
unique  true,false唯一键
unique_for_date  true,false一天只能出现一次
unique_for_month一月只能出现一次
unique_for_year一年只能出现一次
verbose_name别名
validators  自定义校验逻辑

2.生成迁移文件

在终端中(与manage.py同目录下)使用命令python manage.py makemigrations

每一次的迁移都会生成一个迁移文件,对应数据库中的迁移表(django_migrations),迁移文件不能删除,否则会报错

3.同步数据库

 在终端中(与manage.py同目录下)使用命令python manage.py migrate

迁移文件就是为同步到数据库做准备的,django会根据迁移文件中的表,表中的字段生成对应的表

二.测试模型类

该测试中会使用到django中的shell工具,shell工具简单来讲就是交互性的执行命令的一个工具,再打开shell工具测试模型类之前,django会自动连接好数据库,配置环境。进入方式:

在终端中(与manage.py同目录下)使用命令python manage.py shell

导入模型类from books.models import BookInfo

1.增

方式一:

创建一个模型类对象,调用save方法进行保存

book = BookInfo(name = '豪豪爱吃五花肉',chuban_date = '2022-05-01')
book.save()

方式二:

调用模型类中objects的create方法直接创建并保存一条数据

BookInfo.objects.create(name = '豪豪不爱吃肉了',chuban_date = '2022-05-01')

2.查

基本查询

get:查询单一结果,参数为条件,返回一个模型类对象

all:查询集,返回一个集合

count:统计数量

>>> BookInfo.objects.get(name = '豪豪爱吃五花肉')
<BookInfo: 豪豪爱吃五花肉>
>>> BookInfo.objects.all()
<QuerySet [<BookInfo: 西游记>, <BookInfo: 红楼梦>, <BookInfo: 豪豪爱吃猪肉>, <BookInfo: 豪豪爱吃五花肉>, <BookInfo: 豪豪不爱吃肉了>]>
>>> BookInfo.objects.count()
5

过滤查询

get(过滤条件):过滤出一个结果

filter(过滤条件):过滤出多个结果

exclude(过滤条件):过滤出不符合过滤条件的结果

普通过滤

过滤条件语法使用字段__关键字=值进行过滤

exact:相等关键字

contains:包含关键字

查询name包含豪豪的对象

>>> BookInfo.objects.filter(name__contains='豪豪')
<QuerySet [<BookInfo: 豪豪爱吃猪肉>, <BookInfo: 豪豪爱吃五花肉>, <BookInfo: 豪豪不爱吃肉了>]>

isnull:是否为空关键字

in:范围查询

>>> BookInfo.objects.filter(id__in=[1,2,3])
<QuerySet [<BookInfo: 西游记>, <BookInfo: 红楼梦>]>

gt :大于

查询id大于3

>>> BookInfo.objects.filter(id__gt=3)
<QuerySet [<BookInfo: 豪豪爱吃猪肉>, <BookInfo: 豪豪爱吃五花肉>, <BookInfo: 豪豪不爱吃肉了>]>

gte :大于等于

lt :小于 

lte :小于等于

日期相关的过滤

year、month、day、week_day、hour、minute、second

查询2022年出版的图书

BookInfo.objects.filter(chuban_date__year=2022)
<QuerySet [<BookInfo: 西游记>, <BookInfo: 红楼梦>, <BookInfo: 豪豪爱吃猪肉>, <BookInfo: 豪豪爱吃五花肉>, <BookInfo: 豪豪不爱吃肉了>]>

查询2021年后出版的图书

>>> BookInfo.objects.filter(chuban_date__year__gt=2021)
<QuerySet [<BookInfo: 西游记>, <BookInfo: 红楼梦>, <BookInfo: 豪豪爱吃猪肉>, <BookInfo: 豪豪爱吃五花肉>, <BookInfo: 豪豪不爱吃肉了>]>

3.删

方法一:

调用模型对象的delete()方法即可删除

>>> book = BookInfo.objects.get(name = '豪豪爱吃五花肉')
>>> book.delete()
(1, {'books.BookInfo': 1})

方法二:

通过过滤器查找的结果调用delete()方法删除

>>> BookInfo.objects.get(name = '豪豪爱吃猪肉').delete()
(1, {'books.BookInfo': 1})

4.改

方法一:

对查询结果调用update进行修改

>>> BookInfo.objects.filter(name = '三国演义').update(name = '红楼梦')
0

方法二:

对模型类对象单独进行修改,在调用save()进行保存

>>> book = BookInfo.objects.get(name = '西游记')
>>> book.chuban_date='1997-01-01'
>>> book.save()

5.进阶

F对象:

使用方式F('字段名')    导包from django.db.models import F
 

查询阅读量等于评论量的书籍

>>> BookInfo.objects.filter(read_count=F('pinglun_count'))
<QuerySet [<BookInfo: 西游记>, <BookInfo: 红楼梦>, <BookInfo: 豪豪不爱吃肉了>]>

Q对象:

支持使用&与,|或,~非,格式 Q(过滤条件)与或非运算符Q(过滤条件)

导包   from django.db.models import Q

查询评论量大于0和阅读量大于0的图书

>>> BookInfo.objects.filter(Q(read_count__gt=0)&Q(pinglun_count__gt=0))
<QuerySet [<BookInfo: 西游记>]>

聚合函数

Avg(平均),Count(数量),Max(最大),Min(最小),Sum(求和),使用时候需要通过django.db.models导入,使用方式模型类.objects.aggregate(聚合函数名('字段名')),返回值类型:字典

>>> BookInfo.objects.aggregate(Sum('pinglun_count'))
{'pinglun_count__sum': 1}

排序

正序order_by(‘字段’)

倒序order_by(‘-字段’)

>>> BookInfo.objects.all().order_by('-id')
<QuerySet [<BookInfo: 豪豪不爱吃肉了>, <BookInfo: 红楼梦>, <BookInfo: 西游记>]>
>>> BookInfo.objects.all().order_by('id')
<QuerySet [<BookInfo: 西游记>, <BookInfo: 红楼梦>, <BookInfo: 豪豪不爱吃肉了>]>

关联查询

从从表向主表查询

格式(外键__主表的字段名)

查询在西游记中包含的人物

>>> PeopleInfo.objects.filter(book__name='西游记')
<QuerySet [<PeopleInfo: 孙悟空>, <PeopleInfo: 猪八戒>]>

从主表向从表查询

格式(从表的模型类名__从表字段名)

>>> BookInfo.objects.filter(peopleinfo__name='猪八戒')
<QuerySet [<BookInfo: 西游记>]>

三.补充

1.查询集<QuerySet>

调用需要返回多个对象的方法是就会返回一个查询集对象(all()返回全部,filter()返回满足条件的,exclude()返回不满足条件的,order_by()排序),比如:

>>> BookInfo.objects.all()
<QuerySet [<BookInfo: 西游记>, <BookInfo: 红楼梦>, <BookInfo: 豪豪不爱吃肉了>]>

返回的就是一个查询集

查询集可以进行再次过滤操作,也就是说多次过滤。比如:

>>> BookInfo.objects.all().filter(id__gt=3).filter(id=7)
<QuerySet [<BookInfo: 豪豪不爱吃肉了>]>

使用exists()返回查询集是否有数据

>>> BookInfo.objects.all().filter(id__gt=3).filter(id=7).exists()
True

查询集可以进行类似列表的切片操作

2.两大特性

惰性执行

创建查询集不会对数据库的数据进行查询,只有使用数据的时候才会对数据库进行查询

>>> b=BookInfo.objects.all()    //不会对数据库进行查询
>>> b                            //使用数据时才会对数据库进行查询
<QuerySet [<BookInfo: 西游记>, <BookInfo: 红楼梦>, <BookInfo: 豪豪不爱吃肉了>]>

缓存

当使用一个变量去接受查询集的时候,第一次使用查询集会对数据库进行查询,在第二次的时候,会使用这个变量个缓存(减少数据库负载)

这样子django不会进行缓存

>>> BookInfo.objects.all()
<QuerySet [<BookInfo: 西游记>, <BookInfo: 红楼梦>, <BookInfo: 豪豪不爱吃肉了>]>
>>> BookInfo.objects.all()
<QuerySet [<BookInfo: 西游记>, <BookInfo: 红楼梦>, <BookInfo: 豪豪不爱吃肉了>]>

 这样子会把查询集缓存到q中

>>> q=BookInfo.objects.all()
>>> q
<QuerySet [<BookInfo: 西游记>, <BookInfo: 红楼梦>, <BookInfo: 豪豪不爱吃肉了>]>
>>> q
<QuerySet [<BookInfo: 西游记>, <BookInfo: 红楼梦>, <BookInfo: 豪豪不爱吃肉了>]>

3.管理器(Manager)

我们在之前进行增删改查操作时候都会使用模型类去调用objects,这个objects就是django给买一个模型类自动生成的对象。当然也可以自定义管理器对象。


总结

orm框架可以让我们完全不需要使用sql语句就可以对数据库进行各种各样的操作

;