zoukankan      html  css  js  c++  java
  • 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定义在此包中

    本博客仅为本人学习过程中的记录,欢迎一起交流经验。
  • 相关阅读:
    open jdk
    llvm 编译
    llvm Array Bounds Check Elimination
    tmux 共享窗口大小
    llvm pass
    llvm code call graph
    llvm -O 经历过那些pass
    tcmalloc asan
    web ide
    eclipse配置
  • 原文地址:https://www.cnblogs.com/panpanda/p/15162337.html
Copyright © 2011-2022 走看看