视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
一文详解Python网站开发会用到哪些orm框架
2020-11-27 14:21:14 责编:小采
文档


在之前的文章中我们或多或少的介绍了关于Python的知识,并且到了是实战中,我们就要用python开发页面,其实,用框架开发页面,是最简单的,也是最轻松的。本章,我们就要介绍Python页面开发中的用orm框架开发页面。

什么是orm

ORM 即Object Relational Mapping,全称对象关系映射。

可是它到底是干啥的呢?
如果接触过一些web后台的化,我们知道web后台有很大一部分工作都是数据的增删改查,如果每次操作数据库都要连接数据库,构造sql语句,执行sql语句的话,那未免太麻烦了,所以我们可以将数据库中的表,字段,行,与我们的面向对象编程中的类,类的属性,以及对象建立一一对应的映射关系,这样我们便可以避免直接操作数据库,而只要调用相应的方法就可以了。
拿我过去的做法举个例子就明白了,比如实现一个用户注册,以前我是怎么做的,前台拿到数据,传给后台,然后后台字符串拼接形成sql语句,后台执行。
而有了ORM以后,我只需要用数据实例化一个User对象,然后调用该对象的save方法,便保存到了数据库,作为使用者的角度,不需要操作一句sql语句。
假设User类对应users表

user=User(id="100001",name="Andy",password="*****")
user.save() //保存到数据库
user=User.findById("100001") #从数据库中找出id为"100001"的用户
user.update(password="*********") #更改id为"100001"的用户密码
users=User.findAll() #取出users表中全部数据

我就问,这样用起来不爽吗?

注意

IO操作均为异步,用到的异步库为asyncio
链接的数据库为mysql 5.7,用到的mysql异步IO驱动为aiomysql

实现ORM的必要准备---封装数据库操作

创建数据库连接池

import asyncioimport aiomysql 
async def create_pool(**kw):global __pool
__pool=await aiomysql.create_pool(
 host=kw.get('host','localhost'),
 port=kw.get('port',3306),
 user=kw['user'],
 password=kw['password'],
 db=kw['db'],
 charset=kw.get('charset','utf8'),
 autocommit=kw.get('autocommit',True), # 自动提交事务
 maxsize=kw.get('maxsize',10), # 池中最多有10个链接对象
 minsize=kw.get('minsize',1),
)

封装select方法

async def select(sql,args,size=None): //size可以决定取几条
global __pool
with (await __pool) as conn:
 cur=await conn.cursor(aiomysql.DictCursor) 
 # 用参数替换而非字符串拼接可以防止sql注入
 await cur.execute(sql.replace('?','%s'),args) 
 if size:
 rs=await cur.fetchmany(size) 
 else:
 rs=await cur.fetchall() 
 await cur.close()
 return rs

除了select方法要返回查询内容,剩下的update,insert,delete均只需返回一个影响行数,所以可将它们三个封装为一个execute方法

def execute(sql,args):
global __pool
try: 
 with (await __pool) as conn:
 cur=await conn.cursor() 
 await cur.execute(sql.replace('?', '%s'), args)
 affected=cur.rowcount
 await cur.close()
except BaseException as e:
 raise e
return affected

开始动手实现ORM

编程中有个思想叫做”自顶向下“。所以当你对如何设计ORM无从下手的时候,你可以假设已经有一个ORM框架,你想怎么用?

class Model(object):
 async def find(self):
 pass
class User(Model):
 # 注意这里的都是类属性
 __table__="users"
 id=StringField(...)
 name=StringField(...)
user=User(id="10001",name="Andy")
user.save()

有没有发现,这样看User类,很清楚,对应user表,这个表有哪些字段,一目了然。然后让子类继承父类,实现对find,save...等方法的复用。真是完美,可是要怎么实现呢?

字段类的实现

class Field(object):
 def __init__(self,name,column_type,primary_key,default): 
 self.name=name # 字段名
 self.column_type=column_type # 字段数据类型
 self.primary_key=primary_key # 是否是主键
 self.default=default # 有无默认值
 def __str__(self): 
 return '<%s:%s>' % (self.__class__.__name__,self.name) 
 class StringField(Field):
 def __init__(self,name=None,primary_key=False,default=None,ddl='varchar(100)'): 
 super(StringField,self).__init__(name,ddl,primary_key,default)
 # 其它字段略,一个道理,一个模式

下载本文
显示全文
专题