Python的SQLAlchemy框架使用入门


Posted in Python onApril 29, 2015

数据库表是一个二维表,包含多行多列。把一个表的内容用Python的数据结构表示出来的话,可以用一个list表示多行,list的每一个元素是tuple,表示一行记录,比如,包含id和name的user表:

[
  ('1', 'Michael'),
  ('2', 'Bob'),
  ('3', 'Adam')
]

Python的DB-API返回的数据结构就是像上面这样表示的。

但是用tuple表示一行很难看出表的结构。如果把一个tuple用class实例来表示,就可以更容易地看出表的结构来:

class User(object):
  def __init__(self, id, name):
    self.id = id
    self.name = name

[
  User('1', 'Michael'),
  User('2', 'Bob'),
  User('3', 'Adam')
]

这就是传说中的ORM技术:Object-Relational Mapping,把关系数据库的表结构映射到对象上。是不是很简单?

但是由谁来做这个转换呢?所以ORM框架应运而生。

在Python中,最有名的ORM框架是SQLAlchemy。我们来看看SQLAlchemy的用法。

首先通过easy_install或者pip安装SQLAlchemy:

$ easy_install sqlalchemy

然后,利用上次我们在MySQL的test数据库中创建的user表,用SQLAlchemy来试试:

第一步,导入SQLAlchemy,并初始化DBSession:

# 导入:
from sqlalchemy import Column, String, create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base

# 创建对象的基类:
Base = declarative_base()

# 定义User对象:
class User(Base):
  # 表的名字:
  __tablename__ = 'user'

  # 表的结构:
  id = Column(String(20), primary_key=True)
  name = Column(String(20))

# 初始化数据库连接:
engine = create_engine('mysql+mysqlconnector://root:password@localhost:3306/test')
# 创建DBSession类型:
DBSession = sessionmaker(bind=engine)

以上代码完成SQLAlchemy的初始化和具体每个表的class定义。如果有多个表,就继续定义其他class,例如School:

class School(Base):
  __tablename__ = 'school'
  id = ...
  name = ...

create_engine()用来初始化数据库连接。SQLAlchemy用一个字符串表示连接信息:

'数据库类型+数据库驱动名称://用户名:口令@机器地址:端口号/数据库名'

你只需要根据需要替换掉用户名、口令等信息即可。

下面,我们看看如何向数据库表中添加一行记录。

由于有了ORM,我们向数据库表中添加一行记录,可以视为添加一个User对象:

# 创建session对象:
session = DBSession()
# 创建新User对象:
new_user = User(id='5', name='Bob')
# 添加到session:
session.add(new_user)
# 提交即保存到数据库:
session.commit()
# 关闭session:
session.close()

可见,关键是获取session,然后把对象添加到session,最后提交并关闭。Session对象可视为当前数据库连接。

如何从数据库表中查询数据呢?有了ORM,查询出来的可以不再是tuple,而是User对象。SQLAlchemy提供的查询接口如下:

# 创建Session:
session = DBSession()
# 创建Query查询,filter是where条件,最后调用one()返回唯一行,如果调用all()则返回所有行:
user = session.query(User).filter(User.id=='5').one()
# 打印类型和对象的name属性:
print 'type:', type(user)
print 'name:', user.name
# 关闭Session:
session.close()

运行结果如下:

type: <class '__main__.User'>
name: Bob

可见,ORM就是把数据库表的行与相应的对象建立关联,互相转换。

由于关系数据库的多个表还可以用外键实现一对多、多对多等关联,相应地,ORM框架也可以提供两个对象之间的一对多、多对多等功能。

例如,如果一个User拥有多个Book,就可以定义一对多关系如下:

class User(Base):
  __tablename__ = 'user'

  id = Column(String(20), primary_key=True)
  name = Column(String(20))
  # 一对多:
  books = relationship('Book')

class Book(Base):
  __tablename__ = 'book'

  id = Column(String(20), primary_key=True)
  name = Column(String(20))
  # “多”的一方的book表是通过外键关联到user表的:
  user_id = Column(String(20), ForeignKey('user.id'))

当我们查询一个User对象时,该对象的books属性将返回一个包含若干个Book对象的list。
小结

ORM框架的作用就是把数据库表的一行记录与一个对象互相做自动转换。

正确使用ORM的前提是了解关系数据库的原理。

Python 相关文章推荐
分享Python文本生成二维码实例
Jan 06 Python
Python 多进程并发操作中进程池Pool的实例
Nov 01 Python
Python sorted函数详解(高级篇)
Sep 18 Python
Python函数中不定长参数的写法
Feb 13 Python
Python基础教程之if判断,while循环,循环嵌套
Apr 25 Python
python抓取需要扫微信登陆页面
Apr 29 Python
python 标准差计算的实现(std)
Jul 29 Python
将python安装信息加入注册表的示例
Nov 20 Python
python 实现二维字典的键值合并等函数
Dec 06 Python
解析PyCharm Python运行权限问题
Jan 08 Python
Jupyter Notebook 实现正常显示中文和负号
Apr 24 Python
python如何爬取动态网站
Sep 09 Python
python使用post提交数据到远程url的方法
Apr 29 #Python
python实现根据ip地址反向查找主机名称的方法
Apr 29 #Python
连接Python程序与MySQL的教程
Apr 29 #Python
python实现通过代理服务器访问远程url的方法
Apr 29 #Python
python实现带错误处理功能的远程文件读取方法
Apr 29 #Python
python使用socket远程连接错误处理方法
Apr 29 #Python
python使用socket连接远程服务器的方法
Apr 29 #Python
You might like
PHP无限分类代码,支持数组格式化、直接输出菜单两种方式
2011/05/18 PHP
使ecshop模板中可引用常量的实现方法
2011/06/02 PHP
使用PHP生成二维码的两种方法(带logo图像)
2014/03/14 PHP
Prototype使用指南之selector.js
2007/01/10 Javascript
jQuery 标题的自动翻转实现代码
2009/10/14 Javascript
javascript中的缓动效果实现程序
2012/12/29 Javascript
javascript改变position值实现菜单滚动至顶部后固定
2013/01/18 Javascript
在图片上显示左右箭头类似翻页的代码
2013/03/04 Javascript
浅谈关于JavaScript的语言特性分析
2013/04/11 Javascript
window.print打印指定div指定网页指定区域的方法
2014/08/04 Javascript
js中键盘事件实例简析
2015/01/10 Javascript
jQuery头像裁剪工具jcrop用法实例(附演示与demo源码下载)
2016/01/22 Javascript
JavaScript实现图片轮播组件代码示例
2016/11/22 Javascript
多种方式实现js图片预览
2016/12/12 Javascript
vue实现ToDoList简单实例
2017/02/07 Javascript
解决Vue2.x父组件与子组件之间的双向绑定问题
2018/03/06 Javascript
解决vue this.$forceUpdate() 处理页面刷新问题(v-for循环值刷新等)
2018/07/26 Javascript
Vue父组件监听子组件生命周期
2020/09/03 Javascript
Vue实现Header渐隐渐现效果的实例代码
2020/11/05 Javascript
win10系统中安装scrapy-1.1
2016/07/03 Python
Zabbix实现微信报警功能
2016/10/09 Python
Python使用matplotlib绘制正弦和余弦曲线的方法示例
2018/01/06 Python
Python MySQLdb 使用utf-8 编码插入中文数据问题
2018/03/13 Python
Python元组知识点总结
2019/02/18 Python
Tensorflow累加的实现案例
2020/02/05 Python
pycharm实现在子类中添加一个父类没有的属性
2020/03/12 Python
canvas绘制视频封面的方法
2018/02/05 HTML / CSS
Petmate品牌官方网站:宠物用品
2018/11/25 全球购物
武汉世纪畅想数字传播有限公司 .NET笔试题
2015/06/13 面试题
你经历的项目中的SCM配置项主要有哪些?什么是配置项?
2013/11/04 面试题
办理生育手续介绍信
2014/01/14 职场文书
2014年学校安全工作总结
2014/11/13 职场文书
总经理助理岗位职责
2015/01/31 职场文书
中国世界遗产导游词
2015/02/13 职场文书
浅谈golang 中time.After释放的问题
2021/05/05 Golang
Elasticsearch 聚合查询和排序
2022/04/19 Python