Django07_Django框架模型(ORM)

Django07_Django框架模型(ORM)

7.1 ORM模型概述

在之前的学习中通我们操作数据库是直接在命令行中敲sql语句

比如查全部数据库:show databases;

查询一张表下的全部记录: select * from 表名;

但是在实际的网站开发过程中,对于数据库的选择不可能只是mysql, 可能会有其他的数据库,每一个数据库对应的sql语句都会有相应的差异

目前主流的数据有:MySQL Oracle SQLServer sqlite

每一个数据库的语法都会有差异,所以我们不能直接写sql语句

而是希望去找到一个上层的方法

例如:在python中操作mysql,是使用了pymysql这个库,不过最终还是需要我们直接写sql语句, pymysql还是不够上层

所以诞生了orm

orm是数据库的上层,我们只负责调用函数,orm底层会把它翻译成对应的sql语句

Django中内嵌了ORM框架,不需要直接编写SQL语句进行数据库操作,而是通过定义模型类,操作模型类来完成对数据库中表的增删改查和创建等操作。

O是object,也就类对象的意思。

R是relation,翻译成中文是关系,也就是关系数据库中数据表的意思。

M是mapping,是映射的意思。

image-20211008150813304映射:

类:sql语句table表

类成员变量:table表中的字段、类型和约束

类对象:sql表的表记录

ORM的优点

  • 数据模型类都在一个地方定义,更容易更新和维护,也利于重用代码。
  • ORM 有现成的工具,很多功能都可以自动完成,比如数据消除、预处理、事务等等。
  • 它迫使你使用 MVC 架构,ORM 就是天然的 Model,最终使代码更清晰。
  • 基于 ORM 的业务代码比较简单,代码量少,语义性好,容易理解。
  • 新手对于复杂业务容易写出性能不佳的 SQL,有了ORM不必编写复杂的SQL语句, 只需要通过操作模型对象即可同步修改数据表中的数据.
  • 开发中应用ORM将来如果要切换数据库.只需要切换ORM底层对接数据库的驱动【修改配置文件的连接地址即可】

ORM 也有缺点

  • ORM 库不是轻量级工具,需要花很多精力学习和设置,甚至不同的框架,会存在不同操作的ORM。
  • 对于复杂的业务查询,ORM表达起来比原生的SQL要更加困难和复杂。
  • ORM操作数据库的性能要比使用原生的SQL差。
  • ORM 抽象掉了数据库层,开发者无法了解底层的数据库操作,也无法定制一些特殊的 SQL。【自己使用pymysql另外操作即可,用了ORM并不表示当前项目不能使用别的数据库操作工具了。】

ORM数据库操作步骤:

  1. 配置数据库连接信息
  2. 在models.py中定义模型类
  3. 生成数据库迁移文件并执行迁文件**[注意:数据迁移是一个独立的功能,这个功能在其他web框架未必和ORM一块的]**
  4. 通过模型类对象提供的方法或属性完成数据表的增删改查操作

7.2 配置数据库连接

在settings.py中保存了数据库的连接配置信息,Django默认初始配置使用sqlite数据库。

所以我们需要按照MySQL数据库驱动

image-20230807185121525

  1. 安装PyMySQL
pip install PyMySQL
  1. pymysql以mysqldb的模式运行对接ORM
from pymysql import install_as_MySQLdb
install_as_MySQLdb() # 让pymysql以MySQLDB的运行模式和Django的ORM对接运行

让Django的ORM能以mysqldb的方式来调用PyMySQL

image-20230807185534186

  1. 修改 setting配置文件 DATABASES 配置信息
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'HOST': '127.0.0.1',  # 数据库主机
        'PORT': 3306,  # 数据库端口
        'USER': 'root',  # 数据库用户名
        'PASSWORD': '123456',  # 数据库用户密码
        'NAME': 'student'  # 数据库名字
    }
}
  1. 配置打印ORM转SQL的日志信息
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'console':{
            'level':'DEBUG',
            'class':'logging.StreamHandler',
        },
    },
    'loggers': {
        'django.db.backends': {
            'handlers': ['console'],
            'propagate': True,
            'level':'DEBUG',
        },
    }
}
  1. 创建MySQL数据库
create database student; # mysql8.0默认就是utf8mb4;
create database student default charset=utf8mb4; # mysql8.0之前的版本

7.3 定义模型类

  1. 模型类定义在 **子应用/models.py**文件中
  2. 模型类必须直接或间接继承 **django.db.models.Model**类

以学生管理为例进行演示

学生信息、课程信息、老师信息,大概3-4张表

7.3.1 创建子应用 student

image-20230808164434429

7.3.2 注册子应用:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    "ntime",
    "app01",
    "student",
]

7.3.3 引入子应用路由:

    re_path('^student/',include(('student.urls','student'),namespace='student')),

7.3.4 在 student/models.py中定义模型类:

from django.db import models
from datetime import datetime


# Create your models here.

# 模型类必须要直接或者间接继承于 models.Model
class BaseModel(models.Model):
    """公共模型[公共方法和公共字段]"""
    # created_time = models.IntegerField(default=0, verbose_name="创建时间")
    created_time = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
    # auto_now_add 当数据添加时设置当前时间为默认值
    # auto_now= 当数据添加/更新时, 设置当前时间为默认值
    updated_time = models.DateTimeField(auto_now=True)

    class Meta(object):
        abstract = True  # 设置当前模型为抽象模型, 当系统运行时, 不会认为这是一个数据表对应的模型.


class Student(BaseModel):
    """Student模型类"""

    # 1. 字段[数据库表字段对应]
    SEX_CHOICES = (
        (0, "女"),
        (1, "男"),
        (2, "保密"),
    )
    # 字段名 = models.数据类型(约束选项1,约束选项2, verbose_name="注释")
    # SQL: id bigint primary_key auto_increment not null comment="主键",
    id = models.AutoField(primary_key=True, null=False, verbose_name="主键")  # django会自动在创建数据表的时候生成id主键/还设置了一个调用别名 pk

    # SQL: name varchar(20) not null comment="姓名"
    # SQL: key(name),
    name = models.CharField(max_length=20, db_index=True, verbose_name="姓名")

    # SQL: age smallint not null comment="年龄"
    age = models.SmallIntegerField(verbose_name="年龄")

    # SQL: sex tinyint not null comment="性别"
    # sex = models.BooleanField(verbose_name="性别")
    sex = models.SmallIntegerField(choices=SEX_CHOICES, default=2)

    # SQL: class varchar(5) not null comment="班级"
    # SQL: key(class)
    classmate = models.CharField(db_column="class", max_length=5, db_index=True, verbose_name="班级")

    # SQL: description longtext default "" not null comment="个性签名"
    description = models.TextField(default="", max_length=100,verbose_name="个性签名",null=True,blank=True)

    # 2. 数据表结构信息
    class Meta:
        db_table = 'tb_student'  # 指明数据库表名,如果没有指定表明,则默认为子应用目录名_模型名称,例如: users_student
        verbose_name = '学生信息表'  # 在admin站点中显示的名称
        verbose_name_plural = verbose_name  # 显示的复数名称

    # 3. 自定义数据库操作方法
    def __str__(self):
        """定义每个数据对象的显示信息"""
        return "<User %s>" % self.name

类名:Student ==> 表名

类属性:name ==> 表字段

参数:

  • max_length:该字段的最大长度,超过会报错
  • verbose_name: 字段的名称,后面讲后台系统会用上
  • default:如果不赋值,会使用这个默认值
  • null:该字段可以为空
  • blank:后台创建的时候可以为空

(1)数据库表名

模型类中如果没有指定表名称 db_table = 'tb_student', 那么Django 默认以小写 **app应用名称_小写模型类名**为数据库表面

(2)主键

django会为表创建自动增长的主键列,每个模型只能有一个主键列。

如果使用选项设置某个字段的约束属性为主键列(primary_key)后,django不会再创建自动增长的主键列。

class Student(models.Model):
    # django会自动在创建数据表的时候生成id主键/还设置了一个调用别名 pk
    id = models.AutoField(primary_key=True, null=False, verbose_name="主键") # 设置主键

默认创建的主键列属性为id,可以使用pk代替,pk全拼为primary key

(3)属性名称

  • 不能是python的保留关键字。

  • 不允许使用连续的2个下划线,这是由django的查询方式决定的。__ 是关键字来的,不能使用!!!

  • 定义属性时需要指定字段类型,通过字段类型的参数指定选项,语法如下:

    属性名 = models.字段类型(约束选项, verbose_name="注释")
    

**(4)字段类型 **

类型说明
AutoField自动增长的IntegerField,通常不用指定,不指定时Django会自动创建属性名为id的自动增长属性
BooleanField布尔字段,值为True或False
NullBooleanField支持Null、True、False三种值
CharField字符串,参数max_length表示最大字符个数,对应mysql中的varchar
TextField大文本字段,一般大段文本(超过4000个字符)才使用。
IntegerField整数
DecimalField十进制浮点数, 参数max_digits表示总位数, 参数decimal_places表示小数位数,常用于表示分数和价格 Decimal(max_digits=7, decimal_places=2) ==> 99999.99~ 0.00
FloatField浮点数
DateField日期 参数auto_now表示每次保存对象时,自动设置该字段为当前时间。 参数auto_now_add表示当对象第一次被创建时自动设置当前。 参数auto_now_add和auto_now是相互排斥的,一起使用会发生错误。
TimeField时间,参数同DateField
DateTimeField日期时间,参数同DateField
FileField上传文件字段,django在文件字段中内置了文件上传保存类, django可以通过模型的字段存储自动保存上传文件, 但是, 在数据库中本质上保存的仅仅是文件在项目中的存储路径!!
ImageField继承于FileField,对上传的内容进行校验,确保是有效的图片

(5)约束选项

选项说明
null如果为True,表示允许为空,默认值是False。相当于python的None
blank如果为True,则该字段允许为空白,默认值是False。 相当于python的空字符串,“”
db_column字段的名称,如果未指定,则使用属性的名称。
db_index若值为True, 则在表中会为此字段创建索引,默认值是False。 相当于SQL语句中的key
default默认值,当不填写数据时,使用该选项的值作为数据的默认值。
primary_key如果为True,则该字段会成为模型的主键,默认值是False,一般不用设置,系统默认设置。
unique如果为True,则该字段在表中必须有唯一值,默认值是False。相当于SQL语句中的unique

注意:null是数据库范畴的概念,blank是表单验证范畴的

(6)外键

在设置外键时,需要通过on_delete选项指明主表删除数据时,对于外键引用表数据如何处理,在django.db.models中包含了可选常量:

  • CASCADE 级联,删除主表数据时连通一起删除外键表中数据

  • PROTECT 保护,通过抛出ProtectedError异常,来阻止删除主表中被外键应用的数据

  • SET_NULL 设置为NULL,仅在该字段null=True允许为null时可用

  • SET_DEFAULT 设置为默认值,仅在该字段设置了默认值时可用

  • SET() 设置为特定值或者调用特定方法,例如:

    from django.conf import settings
    from django.contrib.auth import get_user_model
    from django.db import models
    
    def get_sentinel_user():
        return get_user_model().objects.get_or_create(username='deleted')[0]
    
    class UserModel(models.Model):
        user = models.ForeignKey(
            settings.AUTH_USER_MODEL,
            on_delete=models.SET(get_sentinel_user),
        )
    
  • DO_NOTHING 不做任何操作,如果数据库前置指明级联性,此选项会抛出IntegrityError异常

商品分类表

idcategory
1蔬菜
2电脑

商品信息表

idgoods_namecid
1冬瓜1
2华为笔记本A12
3茄子1
  1. 当模型字段的on_delete=CASCADE, 删除蔬菜(id=1),则在外键cid=1的商品id1和3就被删除。
  2. 当模型字段的on_delete=PROTECT,删除蔬菜,mysql自动检查商品信息表,有没有cid=1的记录,有则提示必须先移除掉商品信息表中,id=1的所有记录以后才能删除蔬菜。
  3. 当模型字段的on_delete=SET_NULL,删除蔬菜以后,对应商品信息表,cid=1的数据的cid全部被改成cid=null
  4. 当模型字段的on_delete=SET_DEFAULT,删除蔬菜以后,对应商品信息表,cid=1的数据记录的cid被被设置默认值。

7.4 数据迁移

现在我们创建类之后,还不能直接用它,需要将它变成实际的数据表

这一步操作被称为:数据库迁移

7.4.1 生成迁移文件

python manage.py makemigrations

会在你的app下的migrations目录下生成一个py文件,这个就是记录要转换的详细信息

所谓的迁移文件, 是类似模型类的迁移类,主要是描述了数据表结构的类文件.

如果你发现你执行这个指令无效,就把除init之外的文件都删掉

image-20230808173026585

7.4.2 数据同步

python manage.py migrate

实际的建表操作,包括字段的更改,表的更改

image-20230808173320998

注意:

在django内部提供了一系列的功能,这些功能也会使用到数据库,所以在项目搭建以后第一次数据迁移的时候,会看到django项目中其他的数据表被创建了。

其中就有一个django内置的admin站点管理。

# admin站点默认是开启状态的,我们可以通过http://127.0.0.1:8000/admin
# 这个站点必须有个管理员账号登录,所以我们可以在第一次数据迁移,有了数据表以后,就可以通过以下终端命令来创建一个超级管理员账号。
python manage.py createsuperuser

image-20230808173523958

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值