• 周二. 9月 27th, 2022

5G编程聚合网

5G时代下一个聚合的编程学习网

热门标签

Django ORM框架

admin

11月 28, 2021

思考: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定义在此包中

本博客仅为本人学习过程中的记录,欢迎一起交流经验。

发表回复

您的电子邮箱地址不会被公开。