概述
简单说,ORM 就是通过实例对象的语法,完成关系型数据库的操作的技术,是"对象-关系映射"(Object/Relational Mapping) 的缩写。
ORM 把数据库映射成对象。
- 数据库的表(table) --> 类(class)
- 记录(record,行数据)–> 对象(object)
- 字段(field)–> 对象的属性(attribute)
ORM 使用对象,封装了数据库操作,因此可以不碰 SQL 语言。开发者只使用面向对象编程,与数据对象直接交互,不用关心底层数据库。
ORM 有下面这些优点。
- 数据模型都在一个地方定义,更容易更新和维护,也利于重用代码。
- ORM 有现成的工具,很多功能都可以自动完成,比如数据消毒、预处理、事务等等。
- 它迫使你使用 MVC 架构,ORM 就是天然的 Model,最终使代码更清晰。
- 基于 ORM 的业务代码比较简单,代码量少,语义性好,容易理解。
- 你不必编写性能不佳的 SQL。
但是,ORM 也有很突出的缺点。
- ORM 库不是轻量级工具,需要花很多精力学习和设置。
- 对于复杂的查询,ORM 要么是无法表达,要么是性能不如原生的 SQL。
- ORM 抽象掉了数据库层,开发者无法了解底层的数据库操作,也无法定制一些特殊的 SQL。
Django ORM
下面从一个Blog Model定义来看Django ORM能做什么,,为了更好的理解,相关说明已经写在了注释中
# 所有的model都继承自django.db.models.Model
from django.db import models
class Person(models.Model):
# 下面定义了数据表的每个字段和对应的数据类型
# 如果没有定义主键,会自动添加id自增字段/且自动设置为主键
# id = models.AutoField(primary_key=True)
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
salary = models.IntegerField()
department = models.ForeignKey("myapp.Department",on_delete=models.SET(""))
# Person的元数据
class Meta:
# 重新定义数据表的名字为person,如果没有指定此,默认的数表名为 [appname]_person
db_table = 'person'
# Person对象的实例的描述,默认显示为<Person:Person Object>
def __str__(self):
return self.first_name
上面的Person模型会创建如下的数据库
CREATE TABLE person (
"id" serial NOT NULL PRIMARY KEY,
"first_name" varchar(30) NOT NULL,
"last_name" varchar(30) NOT NULL
);
一个django model的经典经典定义包含如四个部分:
- Model Class
- Meta
- str
- Fields
Django ORM能做什么
-
基础查询
实现对数据表的CRUD操作,对于select形式的查询操作,Django会返回一个QuerySet,这里可以简单理解为list(objectc)# 目前person表中的总记录数 Person.objects.count() # first_name为张的用户数 Person.objects.filter(first_name='张').count()
-
聚合函数
Django提供俩种聚合:-
为整个QuerySet生成聚合值,支持的函数有Avg,Count,Max, Min等
# 求salary的平均值 Person.objects.all().aggregate(Avg('salary')) # 求salary的最大值 Person.objects。all().aggregate(Max('salary'))
-
为查询集的每个对象生成聚合值
-
-
Q查询和F查询
-
Q查询:对对象的复杂查询
# 查询first_name以z开头或者last_name以j开头 并且salary大于9000的Person QuerySet query = (Q(first_name__startwith='z') | Q(last_name__startwith='j')) & Q(salary_gt=9000) Person.objects.filter(query)
-
F查询:获取对数据表字段的引用
# 查询first_name中包含l的Person QuerySet Person.objects.filter(first_name__contains=F('l'))
-
Django ORM适合做什么
Django ORM适合做OLTP(事务型)的业务开发,不适合做OLAP(分析型) 型的数据分析
- OLTP型的业务开发一次性涉及的数据量不会太大,大多针对单用户做查询相关的操作,比如我们针对美团这样一个app, 每一个人打开美团app,都是针对当前打开人一个单用户进行数据库操作。
- OLAP型的数据分析一次性涉及的数据量会非常大,ORM框架会对数据结果进行封装,大量的数据会导致效率明显降低。比如生成报表,会聚合数据库的所有的数据,做相关的规整,反应整个业务发展情况,这样的情况,我们使用原生的SQL会更合适。
Django ORM需要注意的地方
- 出现filter,exclude,order_by这样的查询的时候考虑在需要的Field上加上db_index=True
- 不需要所有的数据一定要使用limit,而不是拿到整个数据集之后在做切片
- 使用values_list获取需要的数据,而不是每条记录的所有Field
- 不要使用len(QuerySet),用count()代替;不要使用if QuerySet,用exists()代替
- 复杂的查询(比如表之家按的join),使用rqw_sql (原始的SQL) 代替
Django ORM的核心模块
django.db下有如下三个子模块
- backends:多数据库支持(mysql/sqlite/),通用的sql代码,数据库连接,管理游标等
- migrations:model的更新触发重建表结构的功能,我们在修改了model,在不影响现有数据的前提下重建数据表结构,在使用model创建数据表后,会在当前的app下创建一个migrations.py文件,文件里记录了有那些model以及model中定义了哪些Field。。
- models:对象字段类型的提供,对象管理,基础查询,聚合查询等