使用web.py访问数据库
更新日期:
web.py提供了基本的数据库访问封装,web.database
,可以实现常用的数据库操作,但不能称为ORM。web.py cookbook里展示了常用的功能, 参见http://webpy.github.io/cookbook/,可以以此为起点来了解web.database使用,进而学习其源码。
数据库链接对象
1 | import web |
函数web.database(dbn, **kws)
初始化并返回一个数据库连接,当需要连接多个数据库时多次调用即可。参数dbn是数据库类型,源码(web/db.py, register_database)显示可使用的值有:mysql, postgres, sqlite, firebird, mssql, oracle。
数据库访问操作
首先来看下select:
1 | # Select all entries from table 'mytable' |
传给select()
的第一个参数是数据库表名, 用关键字参数where
传递SQL的where子句。除了表名之外,SQL查询语句的其它部分都是通过关键字参数传递给select()
。以下是select()
支持的其它参数关键字列表。其中_test=True
时select返回是生成的SQL语句,而非查询结果。
- vars - where子句中的变量,实现绑定变量
1
2myvar = dict(name="Bob")
results = db.select('mytable', myvar, where="name = $name") - what - select返回的列,默认是
*
:results = db.select('mytable', what="id,name")
- where
- order
- group
- limit
- offset
- _test
类似的,db.insert()
, db.update()
, db.delete()
的第一个参数都是数据库表名,其它部分由关键字参数传递。
1 | # Insert an entry into table 'mytable' |
另外还有个db.query()
,接受SQL语句字符串作为参数,也支持关键字参数vars的绑定变量和_test。
1 | db = web.database(dbn='postgres', db='mydata', user='dbuser', pw='') |
select()/query()的返回结果
select()/query()的返回结果类型为iterbetter
的迭代器, 每一行的数据为一个dict。 iterbetter定义在中web/utils.py,支持以数组方式result[i]
访问。
支持事务(transaction)
webpy database也是支持事务的,也可嵌套(除sqllit)。具体参见http://webpy.github.io/cookbook/transactions,以下部分也摘自该处。
基本使用模式:
1 | import web |
在python2.5+环境下可在with
语句使用:
1 | from __future__ import with_statement |
web.py database并未实现ORM,但可使用sqlalchemy, 详情见http://webpy.github.io/cookbook/sqlalchemy。
源码web/db.py
web.py database相关的代码可以直接在Github上查看https://github.com/webpy/webpy/blob/master/。
入口函数是database()
, 它根据dbn从dict里查找对应类型数据库的实现类,再用接受到的参数将其初始化。
数据库基类为class DB
,实现了对数据库访问操作, 都是先根据参数生成SQL语句,再由数据库接口执行SQL得到结果。对应于不同类型的数据库,DB
的子类有: MySQLDB, PostgresDB, SqliteDB, FirebirdDB, MSSQLDB, OracleDB. 映射关系保存在_databases = {}
中;统一通过函数def register_database(name, clazz)
添加,例如:
1 | register_database('mysql', MySQLDB) |
在db.py的开始部分先定义了几个异常类,接着是生成SQL语句用到的辅助类和函数。生成SQL的辅助类有:
- SQLParam
- SQLQuery
- SQLLiteral
函数有:
- _sqllist(values)
- reparam(string_, dictionary)
- sqlify(obj)
- sqllist(lst) - _sqllist返回的结果可能会带’()’,而sqllist没有
- sqlors(left, lst)
- sqlwhere(dictionary, grouping=’ AND ‘)
- sqlquote(a)
事务的类为Transaction
, 接下来定义class DB
及其子类。