Day3-编写ORM
1.设计思路
- 在一个Web App中,所有的数据,包括用户信息,用户发布的日志,评论都放在数据库中,本次实战使用MySQL作为数据库。
- Web App中,有许多地方都要用到数据库,访问数据要创建数据库连接,创建游标对象,执行SQL语句,然后要处理异常,清理资源等。
- 首先,要封装数据库的SELECT,INSERT,UPDATE,DELETE语句
- 其次,由于Web框架使用了基于asyncio的aiohttp,这是基于协程的异步模型。Web App框架采用异步IO编程,aiomysql为MySQL数据库提供了异步IO的驱动
一旦决定使用异步,则系统每一层都必须是异步,“开弓没有回头箭”。
1.创建连接池
创建一个全局的连接池,每个HTTP请求都可以从连接池中直接获取数据库连接。使用连接池的好处是不必频繁地打开和关闭数据库连接,而是能复用就尽量复用。
连接池由全局变量__pool存储,缺省情况下将编码设置为utf8,自动提交事务
2.Select
要执行INSERT、UPDATE、DELETE语句,可以定义一个通用的execute()函数
3.Insert, Update, Delete
设计ORM需要从上层调用者角度来设计。我们先考虑如何定义一个User对象,然后把数据库表users和它关联起来。
from orm import Model, StringField, IntegerField
class User(Model):
__table__ = 'users'
id = IntegerField(primary_key=True)
name = StringField()
4.定义metaclass
5.定义Model
2.参考资料
廖雪峰Python-ORM
廖雪峰Python-SQLite
MySQL
aiomysql
深刻理解Python中的元类(metaclass)
lThings to Know About Python Super
3.代码
!/usr/bin/env python3
-*- coding: utf-8 -*-
__author__ = 'Summous'
import asyncio, logging
import aiomysql
async def create_pool(loop, **kw):
'''
创建数据库链接池
:param loop:事件循环处理程序
:param kw:数据库配置参数集合
:return:无
缺省情况下将编码设置为utf8,自动提交事务
'''
logging.info('创建数据库链接池...')
# 创建全局变量
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),
minsize=kw.get('minsize', 1),
loop=loop
)
async def select(sql, args, size=None):
'''
数据库查询函数
:param sql: sql语句
:param args: sql语句中的参数
:param size: 要查询的数量
:return: 查询结果
'''
# logging.log(sql, args)
global __pool
async with __pool.get() as conn:
# 创建一个结果为字典的游标
async with conn.cursor(aiomysql.DictCursor) as cur:
# 执行sql语句,将sql语句中的'?'替换成'%s'
await cur.execute(sql.replace('?',