一、概念

ORM是Python后端Web框架Django的核心思想,"Object Relational Mapping",即对象-关系映射,简称ORM。

一句话理解就是:

  创建一个实例对象,用创建它的类名当做数据表名,用创建它的类属性对应数据表的字段,当对这个实例对象操作时,能够对应MySQL语句。

也就是说,当我们定义了User类,就相当于在数据库中创建了User表。我们使用User类创建一个实例对象,就相当于往表中插入一跳数据。

u = User(uid=123, name="leo", email="leo@163.com", password="")
u.save()

二、ORM的简易实现

# 定义一个元类(继承于type),用于创建User类
class ModelMetaClass(type):
def __new__(cls, name, bases, attrs):
mappings = dict()
for k, v in attrs.items():
if isinstance(v, tuple):
print("Found mapping: %s ==> %s" % (k, v))
mappings[k] = v for k in mappings.keys():
attrs.pop(k) # 将attrs中的属性转化为以下形式
attrs['__mappings__'] = mappings
attrs['__table__'] = name return type.__new__(cls, name, bases, attrs) # 用户定义User类
class User(metaclass=ModelMetaClass):
# 用户定义的属性,在元类调用__new__时,会将属性进行变形(如下注释部分代码)
uid = ('uid', 'int unsigned')
name = ('name', 'varchar(30)')
email = ('email', 'varchar(30)')
password = ('password', 'varchar(30)') # 上述属性变形为以下形式
# __mappings__ = {
# "uid": ('uid', 'int unsigned'),
# "name": ('name', 'varchar(30)'),
# "email": ('email', 'varchar(30)'),
# "password": ('password', 'varchar(30)')
# }
# __table__ = "User" # 在创建示例对象时(表的每条记录),动态设置成员属性,值就是要插入的值
def __init__(self, **kwargs):
for name, value in kwargs.items():
setattr(self, name, value) # 调用save,则相当于执行sql语句
def save(self):
fields = []
args = []
for k, v in self.__mappings__.items():
# 获取所有字段名
fields.append(v[0])
# 获取字段名对应的值
args.append(getattr(self, k, None)) # 给args中的值,如果不是数字,则需要加上引号(SQL中需要加引号,这里加单引号)
args_temp = list()
for temp in args:
if isinstance(temp, int):
args_temp.append(str(temp))
elif isinstance(temp, str):
args_temp.append("""'%s'""" % temp) # 组合SQL
sql = """insert into %s (%s) values (%s)""" % (self.__table__, ','.join(fields), ','.join(args_temp))
print('SQL: %s' % sql) u = User(uid=1234, name="Leo", email="leo001@163.com", password="")
u.save()

如上述代码,我们通过元类的__new__实现了简易的对象-关系映射。Django中的ORM实现要复杂得多,但从这里可以看出一些基本的思想。

我们如果要定义多个表的话,我们可以将构造函数和save方法都抽象到父类里面去:

# 定义一个元类(继承于type),用于创建User类
class ModelMetaClass(type):
def __new__(cls, name, bases, attrs):
mappings = dict()
for k, v in attrs.items():
if isinstance(v, tuple):
print("Found mapping: %s ==> %s" % (k, v))
mappings[k] = v for k in mappings.keys():
attrs.pop(k) # 将attrs中的属性转化为以下形式
attrs['__mappings__'] = mappings
attrs['__table__'] = name return type.__new__(cls, name, bases, attrs) class Model(object, metaclass=ModelMetaClass):
def __init__(self, **kwargs):
for name, value in kwargs.items():
setattr(self, name, value) def save(self):
fields = []
args = []
for k, v in self.__mappings__.items():
# 获取所有字段名
fields.append(v[0])
# 获取字段名对应的值
args.append(getattr(self, k, None)) # 给args中的值,如果不是数字,则需要加上引号(SQL中需要加引号,这里加单引号)
args_temp = list()
for temp in args:
if isinstance(temp, int):
args_temp.append(str(temp))
elif isinstance(temp, str):
args_temp.append("""'%s'""" % temp) # 组合SQL
sql = """insert into %s (%s) values (%s)""" % (self.__table__, ','.join(fields), ','.join(args_temp))
print('SQL: %s' % sql) # 用户定义User类,继承于Model父类,如果这里没有制定MetaClass,则会到父类去找
class User(Model):
# 用户定义的属性,在元类调用__new__时,会将属性进行变形(如下注释部分代码)
uid = ('uid', 'int unsigned')
name = ('name', 'varchar(30)')
email = ('email', 'varchar(30)')
password = ('password', 'varchar(30)') # 上述属性变形为以下形式
# __mappings__ = {
# "uid": ('uid', 'int unsigned'),
# "name": ('name', 'varchar(30)'),
# "email": ('email', 'varchar(30)'),
# "password": ('password', 'varchar(30)')
# }
# __table__ = "User" u1 = User(uid=1234, name="Leo", email="leo001@163.com", password="")
u1.save() u2 = User(uid=1235, name="Jone", email="Jone@163.com", password="")
u2.save()

[Python之路] ORM(对象关系映射)的更多相关文章

  1. Django---静态文件配置,post提交表单的csrf问题(日后细说),创建app子项目和分析其目录,ORM对象关系映射简介,Django操作orm(重点)

    Django---静态文件配置,post提交表单的csrf问题(日后细说),创建app子项目和分析其目录,ORM对象关系映射简介,Django操作orm(重点) 一丶Django的静态文件配置 #we ...

  2. ORM 对象关系映射

    ORM (object relation mapping) 就是将对象数据转换为sql语句并执行 对象关系映射框架 orm 需要做的事情 1 生成创建表的语句 2 插入数据的语句 3 删除数据的语句 ...

  3. Php ORM 对象关系映射

    ORM的全称是Object Relational Mapping,即对象关系映射.它的实质就是将关系数据(库)中的业务数据用对象的形式表示出来,并通过面向对象(Object-Oriented)的方式将 ...

  4. $Django setting.py配置 ,GET、POST深入理解,三件套,orm对象关系映射简介

    1 django中app的概念: 大学:----------------- 项目  信息学院 ----------app01  物理学院-----------app02 ****强调***:创建的每一 ...

  5. ORM对象关系映射

    ORM 总结: ORM:对象关系映射 作用: 1.将定义数据库模型类--> 数据库表 2.将定义数据库模型类中的属性--->数据库表字段 3.将模型对象的操作(add,delete,com ...

  6. Java 自定义注解实现ORM对象关系映射

    一,ORM概念 ORM即Object Relation Mapping,Object就是对象,Relation就是关系数据库,Mapping映射,就是说Java中的对象和关系数据库中的表存在一种对应关 ...

  7. django-模型之(ORM)对象关系映射(一)

    所谓对象关系映射,就是将数据库的一些名字与python中的一些名字相对应,表名-->类名,字段-->属性,操作(增删改查)-->方法.这样,我们就可以通过对Python代码的编辑来对 ...

  8. ORM对象关系映射之GreenDAO源码解析

    上一篇我们学习了GreenDAO的CRUD基本操作,可以说是非常的方便的,而且GreenDAO的效率和性能远远高于其它两款流行的ORM框架,下面是我从官网找的一副它们三个ORM框架之间的性能测试的直观 ...

  9. Python Web框架篇:Django Model ORM(对象关系映射)

    一,基本操作 用于实现面向对象编程语言里不同类型系统的数据之间的转换,换言之,就是用面向对象的方式去操作数据库的创建表以及增删改查等操作. 1.增(create , save): from app01 ...

  10. ORM对象关系映射:

    django配置orm: django使用mysql数据库: 首先cmd创建库 settings配置mysql数据库: DATABASES = { 'default': { 'ENGINE': 'dj ...

随机推荐

  1. python中的类变量和对象变量,以及传值传引用的探究

    http://www.cnblogs.com/gtarcoder/p/5005897.html http://www.cnblogs.com/mexh/p/9967811.html

  2. Python【无引号、单引号、双引号、三引号】

    无引号#数字和数学运算是标准化.有固定格式的>>> print(520) 520>>> print(1+1)2 单引号#文字却能够千变万化>>> ...

  3. python + Pyglet ---播放视频

    记得安装pyglet 包,AVbin(http://avbin.github.io/AVbin/Download.html) 参考链接: Pyglet教程 http://www.hawstein.co ...

  4. 你懂什么是分布式系统吗?Redis分布式锁都不会?

    分布式系统涉及到很多的技术.理论与协议,很多人也说,分布式系统是“入门容易,深入难”,有一些人简历上写着熟悉分布式系统,很多人都是管中窥豹只见一斑. 究竟什么是分布式系统? 分布式系统是由一组通过网络 ...

  5. inline元素、block元素

    inline元素 不会独占一行,相邻的行内元素会排列在同一行内,直到一行排不下才会换行 高.行高.以及外边距和内边距不可改变 宽度就是它的文字或图片的宽度,不可改变,随元素内容变化而变化 内联元素只能 ...

  6. 消息队列: rabbitMQ

    什么是rabbitMQ? rabbitMQ是一款基于AMQP协议的消息中间件,它能够在应用之间提供可靠的消息传输.在易用性,扩展性,高可用性上表现优秀.而且使用消息中间件利于应用之间的解耦,生产者(客 ...

  7. 原型相关的知识点-new的实现原理

    let obj = {}let fn = function(){ this.content = 'zhangsan'} let fn2 = new fn() fn2是fn实例化出来的一个对象,要了解n ...

  8. VS调试 启动vs报错--未启动IIS

    VS调试 启动程序报错——未启动IIS Express Web服务 解决办法: 1.关闭VS. 2.删出项目文件下的".vs"文件. 3.重新启动解决方案. 4.编译,运行OK. ...

  9. js小功能3:一个简单的计算器功能

    html: <input type='text' id='txt1' /> <select id='select'> <option value='+'>+< ...

  10. Flume下读取kafka数据后再打把数据输出到kafka,利用拦截器解决topic覆盖问题

    1:如果在一个Flume Agent中同时使用Kafka Source和Kafka Sink来处理events,便会遇到Kafka Topic覆盖问题,具体表现为,Kafka Source可以正常从指 ...