一、 ORM介绍
(一) ORM简介
对象关系映射(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术。简单的说,ORM是通过使用描述对象和数据库之间映射的元数据,将程序中的对象自动持久化到关系数据库中。那么,到底如何实现持久化呢?一种简单的方案是采用硬编码方式,为每一种可能的数据库访问操作提供单独的方法。
这种方案存在以下不足:
1.持久化层缺乏弹性。一旦出现业务需求的变更,就必须修改持久化层的接口
2.持久化层同时与域模型与关系数据库模型绑定,不管域模型还是关系数据库模型发生变化,毒药修改持久化曾的相关程序代码,增加了软件的维护难度。
ORM提供了实现持久化层的另一种模式,它采用映射元数据来描述对象关系的映射,使得ORM中间件能在任何一个应用的业务逻辑层和数据库层之间充当桥梁。Java典型的ORM中间件有:Hibernate,ibatis,speedframework。
ORM的方法论基于三个核心原则:
简单:以最基本的形式建模数据。
传达性:数据库结构被任何人都能理解的语言文档化。
精确性:基于数据模型创建正确标准化了的结构。
(二) ORM的概念
让我们从O/R开始。字母O起源于"对象"(Object),而R则来自于"关系"(Relational)。几乎所有的程序里面,都存在对象和关系数据库。在业务逻辑层和用户界面层中,我们是面向对象的。当对象信息发生变化的时候,我们需要把对象的信息保存在关系数据库中。
当你开发一个应用程序的时候(不使用O/R Mapping),你可能会写不少数据访问层的代码,用来从数据库保存,删除,读取对象信息,等等。你在DAL中写了很多的方法来读取对象数据,改变状态对象等等任务。而这些代码写起来总是重复的。
ORM解决的主要问题是对象关系的映射。域模型和关系模型分别是建立在概念模型的基础上的。域模型是面向对象的,而关系模型是面向关系的。一般情况下,一个持久化类和一个表对应,类的每个实例对应表中的一条记录,类的每个属性对应表的每个字段。
ORM技术特点:
1.提高了开发效率。由于ORM可以自动对Entity对象与数据库中的Table进行字段与属性的映射,所以我们实际可能已经不需要一个专用的、庞大的数据访问层。
2.ORM提供了对数据库的映射,不用sql直接编码,能够像操作对象一样从数据库获取数据。
(三) ORM的优缺点
ORM的缺点是会牺牲程序的执行效率和会固定思维模式。
从系统结构上来看,采用ORM的系统一般都是多层系统,系统的层次多了,效率就会降低。ORM是一种完全的面向对象的做法,而面向对象的做法也会对性能产生一定的影响。
在我们开发系统时,一般都有性能问题。性能问题主要产生在算法不正确和与数据库不正确的使用上。ORM所生成的代码一般不太可能写出很高效的算法,在数据库应用上更有可能会被误用,主要体现在对持久对象的提取和和数据的加工处理上,如果用上了ORM,程序员很有可能将全部的数据提取到内存对象中,然后再进行过滤和加工处理,这样就容易产生性能问题。
在对对象做持久化时,ORM一般会持久化所有的属性,有时,这是不希望的。
但ORM是一种工具,工具确实能解决一些重复,简单的劳动。这是不可否认的。但我们不能指望工具能一劳永逸的解决所有问题,有些问题还是需要特殊处理的,但需要特殊处理的部分对绝大多数的系统,应该是很少的。
注:以上ORM详细概念来源于博客:https://www.cnblogs.com/strive-man/p/8978014.html
二、 环境配置
为了详细总结django的ORM,依据自己的了解将django分为2.2版本不支持pyMySQL和包含2.1.7以下不支持mysqlclient的版本。这两个版本在数据库配置上存在区别。
(一) Django2.2以下版本
A. 创建数据库
打开Navicat
创建数据库连接
右键已创建的数据库连接进入命令模式
创建数据库
mysql> show databases; // 查看所有数据库
mysql> create database test charset utf8mb4; // 创建数据库,指定编码为utf8,否则会出错
创建新用户,并授权
mysql>create user 新用户名 identified by ‘用户密码’;
mysql>grant all privileges on [数据库名].* to ‘新用户名’@’%’; # 两句功能一样选其一
mysql> grant all on [数据库名].* to ‘新用户名’@’%’;
mysql> FLUSH PRIVILEGES;
B. 项目目录下settings.py的设置
设置DATABASES
DATABASES = {
‘default’: {
‘ENGINE’: ‘django.db.backends.mysql’,
‘NAME’: ‘test’, # 数据库名
‘USER’: ‘root’,
‘PASSWORD’: ‘root’,
‘HOST’: ‘127.0.0.1’,
‘PORT’: ‘3306’,
}
}
激活模型INSTALLED_APPS
C. 在APP目录下的‘init’下添加MySQL设置
import pymysql
pymysql.install_as_MySQLdb()
配置完成
(二) 包括Django2.1.10版本以及以上
完成以上配置,无论哪个版本推荐安装mysqlclient
pip install mysqlclient
pip install default-libmysqlclient-dev # 安装依赖
不需要任何配置
三、 ORM操作
创建models数据库映射示例
class Student(models.Model):
name = models.CharField(verbose_name='姓名', max_length=50)
age = models.SmallIntegerField(verbose_name='年龄', max_length=50, null=True)
sex = models.SmallIntegerField(verbose_name='性别', max_length=50, null=True)
married = models.BooleanField(verbose_name='婚否', default=0, null=True)
is_delete = models.BooleanField(verbose_name='逻辑删除', default=False)
class Meta:
db_table = 'students' # 重置数据表名。默认APP名_数据库类名
verbose_name = '用户信息' # 设置后台快捷数据表名
verbose_name_plural = verbose_name
常用的字段类型映射关系介绍
Int —— IntegetFiled
Varchar —— CharFiled 必须加长度限制
Longtext —— TextFiled
Date —— DateFiled
Datatime —— DatetimeFiled
Bool —— BooleanFiled
Filed常用参数
Primary_key: 指定是否为主键
unique: 指定是否唯一
null: 布尔值true或false 指定是否为空 默认false
blank: 布尔值,当为true表示form表单可为空 默认false
default: 设置默认值
DateFiled.auto_now: 每次修改的时间
DateFiled.auto_now_add: 第一次自动添加创建时间
表关系操作——一对一
class Student(models.Model):
name=省略
sex =省略
class Details(models.Model):
student = models.OneToOneFiled(‘Student’on_delete=models.CASCADE)
// 你删我也删
表关系操作——一对多
class Student(models.Model):
name=省略
sex =省略
grade = models.Foreignkey(‘Grade’,ondelete=models.SET_NULL,null=True)
class Grade(models.Model):
cla_name=省略
num_name =省略
表关系操作——多对多
class Student(models.Model):
name=省略
sex =省略
class Course(models.Model):
project =省略
student = models.ManyToMany(‘Student’,through=‘Enroll’)
class Enroll(models.Model):
student = models.Foreignkey(‘Student’,ondelete= models.CASCADE)
course = models.Foreignkey(‘Course’,ondelete= models.CASCADE)
c_time=省略
paid=省略
数据库增
Student.objects.create(name=’’,age = ’’)
数据库删
stu = Student.objects.get(name=’’)
Stu.delete()
数据库改
stu = Student.objects.get(name=’’)
Stu.name=‘李国庆’
Stu.save()
数据库查
stu = Student.objects.all()
print(stu.query) # 查看所有字段
高级操作
Student.objects.get(pk=1) # 查看第一条
Student.objects.first() # 查看第一条
Student.objects.last() # 查看最后一条
Student.objects.filter(sex=1) # 查看所有性别为男的对象
Student.objects.all().update(sex=0) # 将所有性别为男的对象改为女
Student.objects.filter(age_gt=20) .update(sex=0) #将所有年龄大于20的性别改为女
Student.objects.filter(age =20) .delete() #将所有年龄为20的用户删除
Student.objects.filter(age =20). filter(sex=1) # 筛选年龄为20的男性
Student.objects.exclude(sex=1) # 筛选年龄不为男的
Student.objects.all().order_by(‘age’) # 以年龄为排序字段
Student.objects.all().order_by(‘_age’,’name’) # 年龄倒序,姓名正序
Student.objects.all().order_by(‘_age’,’name’) [:5] # 年龄倒序,姓名正序 前五条
Student.objects.values(‘name’) # 不设值,查所有
Student.objects.only(‘name’) # 区别values,不返回字典形式
Student.objects.defer(‘name’) # 不设值,查所有,不包含name字段
From Django.db.models import Q
Student.objects.filter(Q(age_gt=20)|Q(age=19)) # 查年龄为19或20的人
exact 等于
iexact 忽略大小写,模糊查询
in 包含
gt 小于
gte 大于
startwith 以…开始
istarywith 忽略大小写,以…开始
endwith 以…结尾
iendwith 忽略大小写,以…结尾
isnull 是否为空
统一操作
Student.objects.filter(name__startwith=’李’)
聚合函数
Student.objects.count()计数
Student.objects.filter(name__startwith=’李’).count() # 统计以‘李’开始的个数
from django.db.models import Avg , Max , Min ,Sum
Student.objects.filter(age_avg=Avg(‘age’)) # 平均数
Student.objects.filter(age_ max = Max (‘age’))# 最大值
Student.objects.filter(age_ min = Min (‘age’)) # 最小值
Student.objects.filter(age_sum = Sum (‘age’))# 求和