文章目录
一、django ORM
1. ORM的概念
-
django ORM的概念:
ORM全称Object Relational Mapping(对象关系映射),django有了它,就能够通过python代码操作数据库(在底层转换为sql语句),免去sql语句的书写。
但是,由于抽象程度较高,所以sql语句的执行效率比较低,因此,有些情况下,还是需要我们亲自书写sql语句。
-
映射关系:
ORM是通过以下对应关系,将python代码转换为sql语句的:
python 关系型数据库 类 表 类属性 字段 对象 记录 对象的属性值 记录的字段值
2. 模型类的书写
模型类就是用来映射数据库表的python类,必须写在models.py文件中,必须继承Model类。
比如下面的User类,就是一个模型类。
from django.db import models
class User(models.Model):
id = models.AutoField(primary_key=True)
username = models.CharField(max_length=20)
password = models.IntegerField()
以上python代码等价于下面的MySQL代码:
BEGIN;
--
-- Create model User
--
CREATE TABLE `app01_user` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `username` varchar(20) NOT NULL, `password` integer NOT NULL);
COMMIT;
但此时,我们只是写下了python代码,数据库并没有任何变化。想要代码生效就要进行迁移。
3. 进行迁移
按照顺序在终端中执行以下两条命令:
-
生成迁移:
python manage.py makemigrations
它会检查models.py文件的修改,并生成一份迁移文件。该文件的路径为
app文件夹\migrations\数字前缀_xxxxx.py
。 -
执行迁移:
python manage.py migrate
命令
migrate
只会为在INSTALLED_APPS
里注册了的app进行数据库迁移,将模型真正应用到数据库中。
数据库中的表名为:app名称_模型类的小写形式
。
-
查看对应SQL语句:
执行以下命令,会打印对应的sql语句:python manage.py sqlmigrate app名称 迁移文件名的数字前缀
注意: 每次对模型类进行修改后,都要进行迁移操作!!!
4. Field类的常用选项
模型类中类属性都是一些Field类的实例对象,而这些Field类有以下选项(参数)是必须掌握的:
-
primary_key='布尔值'
:用来定义主键,如果我们在定义模型类时,没有定义主键对应的类属性,那么django会自动帮我们创建一个名为id的主键字段。
-
max_length='整数'
:
指定字段宽度,CharField类必须传入该参数,否则会报错。 -
verbose_name='别名'
:用来给字段取更加直白的别名(可以是中文),在django管理后台中,会以别名显示该字段。
-
null='布尔值'
:设置字段能否为空。 -
default='默认值'
:设置字段的默认值。
二、通过ORM操作数据库
ORM不能操作库,所以库的创建、修改和删除需要我们通过其他方法完成。
1. 创建数据表
就是模型类的书写,已经在上面讲过了。
2. 字段的增删改
-
新增字段:
先在模型类中新增类属性,然后执行迁移。迁移过程可能会提示:
Please select a fix: 1) Provide a one-off default now (will be set on all existing rows with a null value for this column) 2) Quit, and let me add a default in models.py Select an option:
这是因为没有给该字段设置默认值或允许该字段为空。可以:
输入
1
回车,然后提供一个默认值给django:django会自动帮我们将该值设置为该字段的默认值;输入
2
:停止生成迁移文件,开发者到模型类中,设置默认值或设置允许为空后,再重新进行迁移。 -
修改字段:
直接修改模型类中的代码,然后进行迁移即可。
-
删除字段:
直接注释或删除类属性代码,然后进行迁移即可。
如果删除模型类的类属性,执行完迁移后,对应字段的数据都会丢失。所以一定要小心谨慎,最好在迁移前检查一遍代码!!!
3. 记录的增删改查
对于数据的增删改查,通常都应该写在视图当中。如果只是测试一下,可以使用django的shell交互环境:
python manage.py shell
然后就可以导入需要的模块做测试了,下面的命令都可以在shell中允许,但是要先导入对应的模型类。
-
新建记录:
方法一:
模型类名.object.create(属性=值,……)
方法二:
对象 = 模型类名(属性=值,……) # 生成对象 对象.save() # 保存到数据库
-
查询单条记录:
查询集 = 模型类名.object.filter(属性=值,……)
filter方法相当于sql的WHERE子句,该方法的返回值为查询集。查询集也称查询结果集、QuerySet,表示从数据库中获取的对象集合。因此,需要先取出一个对象之后,才能获取具体的值:
对象 = 查询集.first() # 获取第一个对象 值 = 对象.属性 # 获取值
-
查询所有记录:
方法一:
查询集 = 模型类名.object.filter() # 不写任何条件
方法二:
查询集 = 模型类名.object.all()
查询所有记录通常是为了展示给用户,可以使用django模板或jinja2模板的for语句实现,这些模板语句会在以后讲解。
-
修改记录:
方法一:
查询集.update(属性=值,……)
update()
会修改查询集中的所有记录。方法二:
比如hugh是User模型类的一个对象,即数据库中的一条记录,则
hugh.属性 = 值 hugh.save()
上述方法二,在修改字段值的时候,会将所有字段(包括没有修改过的字段)都更新一遍。因此,当记录的字段非常多的时候,效率会十分低。
-
删除记录:
模型类名.object.filter(属性=值,……).delete()
在实际开发中,我们通常都不会真的删除数据,而是进行逻辑删除。即,通过在表中增加一个
is_delete
的布尔类型字段,用来标识一条是否被数据了。将要被删除数据的is_delete
改为1,意味着该字段“被删除”。
4. ORM建立表关系(外键字段的使用)
通常先建表,然后添加外键字段,所以我们先创建表的其他部分。
以图书、作者、出版社为例,假设:图书与作者是多对多关系、图书与出版社是多对一关系、作者与作者详情是一对一关系、作者与出版社没有关系:
from django.db import models
# Create your models here.
class Book(models.Model):
"""图书模型类"""
title = models.CharField(max_length=128)
# 价格字段,总共8位数字,其中小数部分占两位
price = models.DecimalField(max_digits=8, decimal_places=2)
class Author(models.Model):
"""作者模型类"""
name = models.CharField(max_length=32)
class Publisher(models.Model):
"""出版社模型类"""
name = models.CharField(max_length=32)
class AuthorDetail(models.Model):
"""作者详情模型类"""
addr = models.CharField(max_length=128)
-
一对一(
OneToOneField
):作者与作者详情是一对一关系,外键建立在任何一方都可以,但推荐建立在查询频率比较高的一方。
class Author(models.Model): """作者模型类""" …… author_detail = models.OneToOneField(to='AuthorDetail', on_delete=models.CASCADE)
- 参数
to
用来指定关联的模型类(即关联的表),它默认跟作者详情的主键字段关联。 - 想要指定字段可以使用
to_field='关联字段'
参数,但是指定的关联字段必须设置unique=True
。 on_delete=models.CASCADE
参数,用来设置外键记录的删除方法。当删除数据时,与之关联的数据也会被删除。还有其他on_delete
参数选项,在下面有总结。
- 参数
-
一对多(
ForeignKey
):图书与出版社是多对一关系,外键建立在“多的”一方,即图书表中。
class Book(models.Model): """图书模型类""" …… publisher = models.ForeignKey(to='Publisher', on_delete=models.CASCADE)
-
多对多(
ManyToManyField
):图书与作者是多对多关系,按理来说,我们应该新建一张连接表,将对应关系保存在连接表中。但ORM做了优化,它会自动帮我们建立连接表,不需要我们再去手动建立关系表。外键字段建立在任何一方都可以,但是推荐建立在查询频率比较高的一方。
class Book(models.Model): """图书模型类""" …… author = models.ManyToManyField(to='author')
多对多关系中,不用设置
on_delete
参数。 -
ForeignKey
和OneToOneField
生成的字段名称会自动加一个_id
后缀,即publisher
属性在数据库中的字段名为publisher_id
。 -
在django1.x版本中,不需要传入
on_delete
参数,默认就是级联删除CASCADE
。
5. on_delete
参数选项
on_delete参数 | 删除关联表中的数据时,当前表与其关联的field的行为 |
---|---|
on_delete=models.CASCADE | 删除关联数据,与之关联也删除 |
on_delete=models.DO_NOTHING | 删除关联数据,什么也不做 |
on_delete=models.PROTECT | 删除关联数据,引发错误 ProtectedError |
on_delete=models.SET_NULL | 删除关联数据,与之关联的值设置为null(前提FK字段需要设置为可空,一对一同理) |
on_delete=models.SET_DEFAULT | 删除关联数据,与之关联的值设置为默认值(前提FK字段需要设置默认值,一对一同理) |
on_delete=models.SET(值或有返回值的可调用对象) | 删除关联数据,设置为传递给SET()的值 |