django-orm

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

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

M是mapping,是映射的意思。
映射:

类: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并不表示当前项目不能使用别的数据库操作工具了。】
我们可以通过以下步骤来使用django的数据库操作

1
2
3
4

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

使用MySQL数据库首先需要安装驱动程序

1
pip install PyMySQL
在Django的工程同名子目录的__init__.py文件中添加如下语句

1
2
from pymysql import install_as_MySQLdb
install_as_MySQLdb() # 让pymysql以MySQLDB的运行模式和Django的ORM对接运行
作用是让Django的ORM能以mysqldb的方式来调用PyMySQL。
修改DATABASES配置信息

DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'HOST': '127.0.0.1', # 数据库主机
'PORT': 3306, # 数据库端口
'USER': 'root', # 数据库用户名
'PASSWORD': '123', # 数据库用户密码
'NAME': 'student' # 数据库名字
}

在MySQL中创建数据库

create database student; # mysql8.0默认就是utf8mb4;
create database student default charset=utf8mb4; # mysql8.0之前的版本

注意3: 如果想打印orm转换过程中的sql,需要在settings中进行如下配置:
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console':{
'level':'DEBUG',
'class':'logging.StreamHandler',
},
},
'loggers': {
'django.db.backends': {
'handlers': ['console'],
'propagate': True,
'level':'DEBUG',
},
}
}  
6.2、定义模型类
定义模型类

模型类被定义在"子应用/models.py"文件中。
模型类必须直接或者间接继承自django.db.models.Model类。
接下来以学生管理为例进行演示。[系统大概3-4表,学生信息,课程信息,老师信息],创建子应用student,注册子应用并引入子应用路由.

settings.py,代码:
INSTALLED_APPS = [
# ...
'student',
]
urls.py,总路由代码:
urlpatterns = [
# 省略,如果前面有重复的路由,改动以下。
path("student/", include("student.urls")),
]
在models.py 文件中定义模型类。
from django.db import models
from datetime import datetime

模型类必须要直接或者间接继承于 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="", verbose_name="个性签名")

#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

from django.db import models
from datetime import datetime

模型类必须要直接或者间接继承于 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="", verbose_name="个性签名")

#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

from django.db import models
from datetime import datetime

模型类必须要直接或者间接继承于 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="", verbose_name="个性签名")

#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

默认创建的主键列属性为id,可以使用pk代替,pk全拼为primary key。
不能是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

posted @   听雨潇湘  阅读(98)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
点击右上角即可分享
微信分享提示