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中利用Scipy包的SIFT方法进行图片识别的实例教程
Jun 03 Python
Python正则表达式使用经典实例
Jun 21 Python
Swift 3.0在集合类数据结构上的一些新变化总结
Jul 11 Python
Python脚本实现Web漏洞扫描工具
Oct 25 Python
Python实现Windows和Linux之间互相传输文件(文件夹)的方法
May 08 Python
Python正则表达式完全指南
May 25 Python
opencv python 图像去噪的实现方法
Aug 31 Python
浅析PEP572: 海象运算符
Oct 15 Python
Python导入模块包原理及相关注意事项
Mar 25 Python
python3 正则表达式基础廖雪峰
Mar 25 Python
Python如何输出警告信息
Jul 30 Python
django上传文件的三种方式
Apr 29 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
人族 TERRAN 概述
2020/03/14 星际争霸
PHP获取网站域名和地址的代码
2008/08/17 PHP
PHP读取文件或采集时解决中文乱码
2021/03/09 PHP
ExtJs事件机制基本代码模型和流程解析
2010/10/24 Javascript
分享10篇优秀的jQuery幻灯片制作教程及应用案例
2011/04/16 Javascript
十个迅速提升JQuery性能让你的JQuery跑得更快
2012/12/10 Javascript
js获得指定控件输入光标的坐标兼容IE,Chrome,火狐等多种主流浏览器
2013/05/21 Javascript
js简易namespace管理器 实例代码
2013/06/21 Javascript
js实现两个值相加alert出来精确到指定位
2013/09/25 Javascript
js实现可拖动DIV的方法
2013/12/17 Javascript
node.js实现BigPipe详解
2014/12/05 Javascript
js判断登陆用户名及密码是否为空的简单实例
2016/05/16 Javascript
获取jqGrid中选择的行的数据
2016/11/30 Javascript
鼠标经过出现气泡框的简单实例
2017/03/17 Javascript
vue的全局提示框组件实例代码
2018/02/26 Javascript
jQuery发请求传输中文参数乱码问题的解决方案
2018/05/22 jQuery
python进阶教程之循环相关函数range、enumerate、zip
2014/08/30 Python
Python利用Beautiful Soup模块修改内容方法示例
2017/03/27 Python
关于python的list相关知识(推荐)
2017/08/30 Python
python multiprocessing多进程变量共享与加锁的实现
2019/10/02 Python
python 通过视频url获取视频的宽高方式
2019/12/10 Python
keras tensorflow 实现在python下多进程运行
2020/02/06 Python
Jupyter notebook无法导入第三方模块的解决方式
2020/04/15 Python
基于OpenCV的路面质量检测的实现
2020/11/04 Python
使用html5+css3来实现slider切换效果告别javascript+css
2013/01/08 HTML / CSS
德国鞋子网上商店:Omoda.de
2017/03/31 全球购物
波兰运动鞋网上商店:e-Sporting
2018/02/16 全球购物
英国儿童设计师服装和玩具购物网站:Zac & Lulu
2020/10/19 全球购物
动漫专业高职生职业生涯规划书
2014/02/15 职场文书
医药公司采购员岗位职责
2014/09/12 职场文书
校园运动会广播稿
2014/10/06 职场文书
2015年财务经理工作总结
2015/05/13 职场文书
2016年九九重阳节活动总结
2016/04/01 职场文书
Python图片检索之以图搜图
2021/05/31 Python
springboot集成redis存对象乱码的问题及解决
2022/06/16 Java/Android
tree shaking对打包体积优化及作用
2022/07/07 Java/Android