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 selenium鼠标键盘操作(ActionChains)
Apr 12 Python
利用Tkinter(python3.6)实现一个简单计算器
Dec 21 Python
python+matplotlib绘制简单的海豚(顶点和节点的操作)
Jan 02 Python
python tensorflow学习之识别单张图片的实现的示例
Feb 09 Python
python logging重复记录日志问题的解决方法
Jul 12 Python
Python列表推导式与生成器用法分析
Aug 02 Python
numpy 计算两个数组重复程度的方法
Nov 07 Python
基于python实现高速视频传输程序
May 05 Python
Python3从零开始搭建一个语音对话机器人的实现
Aug 23 Python
Python使用Socket实现简单聊天程序
Feb 28 Python
python批量修改xml属性的实现方式
Mar 05 Python
Eclipse配置python默认头过程图解
Apr 26 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 excel类 phpExcel使用方法介绍
2010/08/21 PHP
php 修改、增加xml结点属性的实现代码
2013/10/22 PHP
php强制文件下载而非在浏览器打开的自定义函数分享
2014/05/08 PHP
PHP读书笔记_运算符详解
2016/07/01 PHP
PHP简单获取网站百度搜索和搜狗搜索收录量的方法
2016/08/23 PHP
动态加载js的几种方法
2006/10/23 Javascript
javascript 图片裁剪技巧解读
2012/11/15 Javascript
使用javascript控制cookie显示和隐藏背景图
2014/02/12 Javascript
jQuery通过deferred对象管理ajax异步
2016/05/20 Javascript
js匿名函数使用&amp;传参(实例)
2017/09/08 Javascript
jQuery实现验证表单密码一致性及正则表达式验证邮箱、手机号的方法
2017/12/05 jQuery
Webpack打包字体font-awesome的方法示例
2018/04/26 Javascript
JavaScript&quot;模拟事件&quot;的注意要点详解
2019/02/13 Javascript
M2实现Nodejs项目自动部署的方法步骤
2019/05/05 NodeJs
elementUI table表格动态合并的示例代码
2019/05/15 Javascript
layui的数据表格+springmvc实现搜索功能的例子
2019/09/28 Javascript
Jquery异步上传文件代码实例
2019/11/13 jQuery
vue移动端的左右滑动事件详解
2020/06/17 Javascript
electron踩坑之remote of undefined的解决
2020/10/06 Javascript
js异步接口并发数量控制的方法示例
2020/11/22 Javascript
解决Python网页爬虫之中文乱码问题
2018/05/11 Python
Python minidom模块用法示例【DOM写入和解析XML】
2019/03/25 Python
python的pygal模块绘制反正切函数图像方法
2019/07/16 Python
Python如何使用Gitlab API实现批量的合并分支
2019/11/27 Python
Django配置跨域并开发测试接口
2020/11/04 Python
利用CSS3实现圆角的outline效果的教程
2015/06/05 HTML / CSS
加拿大女装网上购物:Reitmans
2016/10/20 全球购物
最新的小工具和卓越的产品设计:Oh That Tech!
2019/08/07 全球购物
类成员函数的重载、覆盖和隐藏区别
2016/01/27 面试题
医大实习自我鉴定
2013/12/07 职场文书
建筑安全生产责任书
2014/07/22 职场文书
2014优秀党员事迹材料
2014/08/14 职场文书
2014年企业团支部工作总结
2014/12/10 职场文书
入党政审材料范文
2014/12/24 职场文书
扩展多台相同的Web服务器
2021/04/01 Servers
Python-OpenCV实现图像缺陷检测的实例
2021/06/11 Python