Django ORM框架
思考:Django操作数据库中的数据(增删改查),都有哪些方式可以实现呢?
首先,肯定能想到的方式一:使用三方数据库操作模块,执行原生的sql语句对数据库进行操作,如pymysql模块,但此种方式势必存在以下问题:
1. sql语句一般比较复杂,并且维护困难
2. sql语句的安全性无法得到保障,可能会有sql注入的风险
3. 数据库的创建、数据表的生成、数据备份以及数据库的迁移非常麻烦
4. sql语句性能无法保障
其次,方式二就是本篇文章主要要说的:通过ORM框架操作数据库
在介绍ORM框架之前,先看看mysql都有哪些对象?
1. 数据库
2. 数据表
3. 字段
4. 记录
那么,ORM框架与这些对象又有什么关系?
1. 数据库 --> 需要提前手动创建数据库
2. 数据表 --> 与ORM框架中的模型类一一对应
3. 字段 --> 与ORM框架中模型类的类属性一一对应
4. 记录 --> 与ORM框架中模型类的实例一一对应
在通过ORM框架操作数据库之前,需要对使用的数据库进行配置:
1. 在全局配置文件settings.py的DATABASES字典中配置需要连接的数据库信息
2. Django默认使用的数据库是sqlite3(关系型文本数据库)
3. 数据库配置格式如下:
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': BASE_DIR / 'db.sqlite3', } }
注:
default 为数据库的别名(标签)
ENGINE 指定数据库引擎,Django默认支持5种数据库引擎:mysql、oracle、postgresql、postgresql_psycopg2,如果要使用其他的数据库,如redis、mongo等,需要安装对应的模块后再另行配置,此处不展开。
NAME 指定数据库名称,如果使用的是sqlite3,需要自定sqlite3文件的绝对路径
4. 配置mysql数据库信息示例:
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'mysqlDB', 'USER': 'root', 'PASSWORD': '123456', 'PORT': 3306, 'HOST': '127.0.0.1' } }
方便起见,我用的是Django默认数据库sqlite3,配置信息没有更改
PS:使用编辑器pycharm连接sqlite数据库示例
配置完数据库信息,就可以定义模型类了:
1. 一般在子应用的models.py文件中定义模型类(相当于数据库中的一张表)
2. 模型类必须继承Model或者Model的子类
3. 模型类中定义的类属性(相当于数据表中的字段),必须是Field的子类
class Projects(models.Model): name = models.CharField(max_length=50, verbose_name="项目名称", help_text="项目名称", unique=True) leader = models.CharField(max_length=10, verbose_name="项目负责人", help_text="项目负责人") is_execute = models.BooleanField(verbose_name="是否启动项目", help_text="是否启动项目", default=True) desc = models.TextField(verbose_name="项目描述信息", help_text="项目描述信息", null=True, blank=True, default='') create_time = models.DateTimeField(verbose_name="创建时间", help_text="创建时间", auto_now_add=True) update_time = models.DateTimeField(verbose_name="更新时间", help_text="更新时间", auto_now=True) class Meta: db_table = "tb_projects"
4. 定义类属性时,常用的Field子类:
1)CharField --> varchar
2)IntegerField --> integer
3)BooleanField --> bool
4)TextField --> longtext
5)DateTimeField --> datetime
......
5. 定义类属性时,field子类常用options:
1)verbose_name:admin后台中该字段的别名
2)help_text:通过表单小部件来展示该字段额外的help信息,值一般与verbose_name保持一致即可
3)unique:该字段设置唯一约束,默认值为False
4)default:为该字段设置默认值
5)blank:该字段是否允许前端传递空字符串,默认值为False
6)null:该字段是否允许前端传递null,默认值为False
7)auto_now:DateTimeField的实例参数,保存数据时该字段值会自动保存为当前时间,每次执行save方法时都会将当前时间保存
8)auto_now_add:DateTimeField的实例参数,创建数据时该字段值会自动保存为当前时间,之后更新数据该字段值不会再更新
6. 可以在任意一个模型类中定义Meta内部类,用于修改数据库的元数据信息,如:
1)在Meta内部类中,定义类属性 db_table 的值,即为该模型类对应生成的数据表的表名;
2)在Meta内部类中,定义类属性 verbose_name 的值,即为该模型类对应生成的数据表的描述信息;
3)在Meta内部类中,定义类属性 abstract=True ,指定当前模型类为抽象模型类,在迁移时不会生成数据表;
4)在Meta内部类中,定义类属性 ordering=['字段名'] ,指定该模型类对应生成的数据表数据的排序字段,默认按照id排序
7. 表与表之间的关联关系的定义:
1)ForeignKey --> 一对多,一般在‘多’的那个模型类中定义外键字段,如:一个项目会有多个接口,一般在接口表中定义外键字段
必传参数:to ,即和谁建立外键关系,有三种传值方式:
第一种:导入要建立外键关系的模型类(一般称为主表模型类),传递该模型类的引用;
第二种:字符串,子应用名.模型类名,此种方式无需导入
第三种:字符串,self,表示自关联(自己关联自己)
必传参数:on_delete ,即指定主表数据删除后,从表数据的删除策略
model.CASCADE 主表数据删除后,相应的从表数据也删除
model.SET_NULL 主表数据删除后,相应的从表数据设置为null,前提:从表字段必须设置null=True
model.SET_DEFAULT 主表数据删除后,相应的从表数据设置为默认值,前提:从表字段必须设置默认值default=xx
model.PROTECT 主表数据删除时,如果从表有对应的数据,则会报错
class Interfaces(models.Model): name = models.CharField(max_length=50, verbose_name="接口名称", help_text="接口名称", unique=True) tester = models.CharField(max_length=10, verbose_name="测试人员", help_text="测试人员") desc = models.TextField(verbose_name="接口描述信息", help_text="接口描述信息", null=True, blank=True, default='') create_time = models.DateTimeField(verbose_name="创建时间", help_text="创建时间", auto_now_add=True) update_time = models.DateTimeField(verbose_name="更新时间", help_text="更新时间", auto_now=True) projects = models.ForeignKey("projects.Projects", on_delete=models.CASCADE, verbose_name="所属项目", help_text="所属项目") class Meta: db_table = "tb_interfaces" verbose_name = "接口表" verbose_name_plural = "接口表"
2)ManyToManyField --> 多对多,可以在任意一个模型类中使用 ManyToManyField
3)OneToOneField --> 一对一,可以在任意一个模型类中使用 OneToOneField
8. Django模型类转化为数据表
1)生成迁移脚本:进入项目虚拟环境,执行命令 python manage.py makemigrations 子应用名
注:如果不指定子应用名,会把所有子应用都生成迁移脚本
查看生成的迁移脚本内容,如下图
注:定义模型类时,未定义主键,默认会自动创建一个名为id的自增主键。
2)执行迁移脚本:进入项目虚拟环境,执行命令 python manage.py migrate 子应用名
注:生成的数据表名默认为:子应用名_模型类名小写;如果内部类Meta中定义了db_table属性,则数据表名为db_table的值
对定义了外键字段的模型类进行迁移,并查看生成的数据表中外键字段的显示
外键字段名显示为:模型类中定义的外键字段名_id
可以使用命令 python manage.py sqlmigrate 子应用名 迁移脚本名 来查看迁移脚本生成的sql语句
9. BaseModel的定义:
1)目的:精简模型类代码,将公共字段抽取出来,定义在BaseModel中,需要用到公共字段的模型类,继承BaseModel即可
2)BaseModel 没有必要生成数据表,需要在定义BaseModel时,在其内部类Meta中设置abstract=True,即表明当前模型类为抽象模型类,迁移时不会创建表,仅仅用于其他模型类继承
3)位置:一般会创建utils包,将BaseModel定义在此包中