1. ORM框架介绍
对象关系映射(Object Relational Mapping
, 简称ORM
)模式是一种为了解决面向对象与关系数据库存在互不匹配的现象的技术。ORM
框架是连接数据库的桥梁,只要提供了持久化类与表的映射关系,ORM
框架在运行时就能参照映射文件的信息,把对象持久化到数据库中。
ORM框架:为了解决面向对象与关系数据库的互不匹配的现象的框架。
当前ORM
框架主要有五种:
Hibernate
全自动写SQL
语句iBATIS
半自动,自己写SQL
语句,可操作性强,小巧mybatis
eclipseLink
JFinal
2. ORM的由来
让我们从O/R
开始。字母O
起源于"对象"(Object
),而R
则来自于"关系"(Relational
)。
几乎所有的软件开发过程中都会涉及到对象和关系数据库。在用户层面和业务逻辑层面,我们是面向对象的。当对象的信息发生变化的时候,我们就需要把对象的信息保存在关系数据库中。
按照之前的方式来进行开发就会出现程序员会在自己的业务逻辑代码中夹杂很多SQL
语句用来增加、读取、修改、删除相关数据,而这些代码通常都是重复的。
3. 为什么要使用ORM
当我们实现一个应用程序时(不使用ORM
),我们可能会写特别多数据访问层的代码,从数据库保存、删除、读取对象信息,而这些代码是重复的。而使用ORM
则会大大减少重复性代码。对象关系映射(Object Relational Mapping
,简称ORM
),主要实现程序对象到关系数据库数据的映射。
4. 对象–关系映射的优点
- 简单:
ORM
以最基本的形式建模数据。比如ORM
会将MySQL
的一张表映射成一个类(模型),表的字段就是这个类的成员变量。 - 精确:
ORM
使所有的MySQL
数据表都按照统一的标准精确地映射成面向对象编程的类方法,使系统在代码层面保持精准统一。 - 易懂:
ORM
使数据库结构文档化。比如MySQL
数据库就被ORM
转换为了程序员可以读懂的面向对象编程的类,程序员可以只把注意力放在他擅长的面向对象编程语言代码的类层面。 - 易用:
ORM
包含了对持久类对象进行CRUD
操作的API
,例如create()
、update()
、save()
、load()
、find()
、find_all()
、where()
等,也就是将SQL
查询全部封装成了编程语言中的函数,通过函数的链式组合生成最终的SQL
语句。通过这种封装避免了不规范、冗余、风格不统一的SQL
语句、可以避免多人开发造成的bug
,方便编码风格的统一和后期维护。
5. Django中的ORM
5.1 Django项目中使用MySQL数据库
在Django
项目的settings.py
文件中,配置数据库连接信息:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql', # 连接的数据库类型
'NAME': 'name', # 数据库名称
'HOST': '127.0.0.1', # 连接数据库的地址
'PORT': 3306, # 端口
'USER': 'root', # 用户名
'PASSWORD': '123456', # 密码
}
}
在Django
项目的__init__.py
文件中写下如下代码,告诉Django
使用pymysql
模块连接MySQL
数据库:
import pymysql
pymysql.install_as_MySQLdb()
5.2 Model
在Django
中model
是你数据的单一、明确的信息来源。它包含了你存储数据的重要字段和行为。通常,一个模型(Model
)映射到一个数据库表。
基本情况:
- 每个模型都是一个
Python
类,它是django.db.models.Model
的子类。 - 模型的每个属性都代表一个数据库字段。
- 综上所述,
Django
提供了一个自动生成的数据库访问API
。
Model
与数据库的对应关系如下:
ORM | DB |
---|---|
类 | 数据表 |
对象 | 数据行 |
属性 | 字段 |
6. Django ORM常用字段和参数
6.1 常用字段
- AutoField——
int
自增列,必须填入参数primary_key=True
。当Model
中如果没有自增列,则会自动创建一个列名为id
的列。 - IntegerField——一个整数类型,范围在 -2147483648 to 2147483647。
- CharField——字符类型,必须提供
max_length
参数,max_length
表示字符长度。 - DataField——日期字段,日期格式
YYYY-MM-DD
,相当于Python
中的datetime.date()
实例。 - DataTimeField——日期时间字段,格式
YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]
,相当于Python
中的datetime.datetime()
实例。
6.2 字段合集
AutoField(Field)
- int自增列,必须填入参数 primary_key=True
BigAutoField(AutoField)
- bigint自增列,必须填入参数 primary_key=True
注:当model中如果没有自增列,则自动会创建一个列名为id的列
from django.db import models
class UserInfo(models.Model):
# 自动创建一个列名为id的且为自增的整数列
username = models.CharField(max_length=32)
class Group(models.Model):
# 自定义自增列
nid = models.AutoField(primary_key=True)
name = models.CharField(max_length=32)
SmallIntegerField(IntegerField):
- 小整数 -32768 ~ 32767
PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)
- 正小整数 0 ~ 32767
IntegerField(Field)
- 整数列(有符号的) -2147483648 ~ 2147483647
PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)
- 正整数 0 ~ 2147483647
BigIntegerField(IntegerField):
- 长整型(有符号的) -9223372036854775808 ~ 9223372036854775807
自定义无符号整数字段
class UnsignedIntegerField(models.IntegerField):
def db_type(self, connection):
return 'integer UNSIGNED'
PS: 返回值为字段在数据库中的属性,Django字段默认的值为:
'AutoField': 'integer AUTO_INCREMENT',
'BigAutoField': 'bigint AUTO_INCREMENT',
'BinaryField': 'longblob',
'BooleanField': 'bool',
'CharField': 'varchar(%(max_length)s)',
'CommaSeparatedIntegerField': 'varchar(%(max_length)s)',
'DateField': 'date',
'DateTimeField': 'datetime',
'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)',
'DurationField': 'bigint',
'FileField': 'varchar(%(max_length)s)',
'FilePathField': 'varchar(%(max_length)s)',
'FloatField': 'double precision',
'IntegerField': 'integer',
'BigIntegerField': 'bigint',
'IPAddressField': 'char(15)',
'GenericIPAddressField': 'char(39)',
'NullBooleanField': 'bool',
'OneToOneField': 'integer',
'PositiveIntegerField': 'integer UNSIGNED',
'PositiveSmallIntegerField': 'smallint UNSIGNED',
'SlugField': 'varchar(%(max_length)s)',
'SmallIntegerField': 'smallint',
'TextField': 'longtext',
'TimeField': 'time',
'UUIDField': 'char(32)',
BooleanField(Field)
- 布尔值类型
NullBooleanField(Field):
- 可以为空的布尔值
CharField(Field)
- 字符类型
- 必须提供max_length参数, max_length表示字符长度
TextField(Field)
- 文本类型
EmailField(CharField):
- 字符串类型,Django Admin以及ModelForm中提供验证机制
IPAddressField(Field)
- 字符串类型,Django Admin以及ModelForm中提供验证 IPV4 机制
GenericIPAddressField(Field)
- 字符串类型,Django Admin以及ModelForm中提供验证 Ipv4和Ipv6
- 参数:
protocol,用于指定Ipv4或Ipv6, 'both',"ipv4","ipv6"
unpack_ipv4, 如果指定为True,则输入::ffff:192.0.2.1时候,可解析为192.0.2.1,开启刺功能,需要protocol="both"
URLField(CharField)
- 字符串类型,Django Admin以及ModelForm中提供验证 URL
SlugField(CharField)
- 字符串类型,Django Admin以及ModelForm中提供验证支持 字母、数字、下划线、连接符(减号)
CommaSeparatedIntegerField(CharField)
- 字符串类型,格式必须为逗号分割的数字
UUIDField(Field)
- 字符串类型,Django Admin以及ModelForm中提供对UUID格式的验证
FilePathField(Field)
- 字符串,Django Admin以及ModelForm中提供读取文件夹下文件的功能
- 参数:
path, 文件夹路径
match=None, 正则匹配
recursive=False, 递归下面的文件夹
allow_files=True, 允许文件
allow_folders=False, 允许文件夹
FileField(Field)
- 字符串,路径保存在数据库,文件上传到指定目录
- 参数:
upload_to = "" 上传文件的保存路径
storage = None 存储组件,默认django.core.files.storage.FileSystemStorage
ImageField(FileField)
- 字符串,路径保存在数据库,文件上传到指定目录
- 参数:
upload_to = "" 上传文件的保存路径
storage = None 存储组件,默认django.core.files.storage.FileSystemStorage
width_field=None, 上传图片的高度保存的数据库字段名(字符串)
height_field=None 上传图片的宽度保存的数据库字段名(字符串)
DateTimeField(DateField)
- 日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]
DateField(DateTimeCheckMixin, Field)
- 日期格式 YYYY-MM-DD
TimeField(DateTimeCheckMixin, Field)
- 时间格式 HH:MM[:ss[.uuuuuu]]
DurationField(Field)
- 长整数,时间间隔,数据库中按照bigint存储,ORM中获取的值为datetime.timedelta类型
FloatField(Field)
- 浮点型
DecimalField(Field)
- 10进制小数
- 参数:
max_digits,小数总长度
decimal_places,小数位长度
BinaryField(Field)
- 二进制类型
6.3 自定义字段
class UnsignedIntegerField(models.IntegerField):
def db_type(self, connection):
return 'integer UNSIGNED'
自定义char
类型字段:class FixedCharField(models.Field)
:
class FixedCharField(models.Field):
"""
自定义的char类型的字段类
"""
def __init__(self, max_length, *args, **kwargs):
self.max_length = max_length
super(FixedCharField, self).__init__(max_length=max_length, *args, **kwargs)
def db_type(self, connection):
"""
限定生成数据库表的字段类型为char,长度为max_length指定的值
"""
return 'char(%s)' % self.max_length
class Person(models.Model):
# 使用自定义的char类型的字段
name = FixedCharField(max_length=32)
age = models.IntegerField()
birthday = models.DateField()
6.4 字段参数
- null——用于表示某个字段可以为空。
- unique——如果设置为
unique=True
,则该字段在此表找中必须是唯一的。 - db_index——如果
db_index=True
则代表着为此字段设置索引。 - default——为该字段设置默认值。
6.5 DataField和DataTimeField
- auto_now_add——配置
auto_now_add=True
,创建数据记录的时候会把当前时间添加到数据库。 - auto_now——配置上
auto_now=True
,每次更新数据记录的时候会更新该字段。
5. 总结
ORM
框架,就是通过将SQL
语句的增删查改等DML(Data Manipulation Language
数据操纵语言),用类封装起来,变成一个个的类接口方法,如create(), update(), save(), load(), find(), find_all(),where()
。
首先需要我们去调用面向对象编程语言内嵌的模板类的模板方法models.model.xxx
, 构建好具体的数据库表模型,然后由ORM
框架去将这些方法,映射转变为相应的 SQL
语句,然后再将这些 SQL
语句提交给数据库,从而间接完成与数据库的交流。
总之,使用ORM
框架,就是用模型,也就是在某文件1内的DML
建表操作,然后在另外的文件2内,写入其他的DML
操作,如增删查改等等。