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操作xml文件示例
Apr 07 Python
Python装饰器decorator用法实例
Nov 10 Python
python学习之编写查询ip程序
Feb 27 Python
python3 shelve模块的详解
Jul 08 Python
itchat和matplotlib的结合使用爬取微信信息的实例
Aug 25 Python
python zip,lambda,map函数代码实例
Apr 04 Python
python自定义函数def的应用详解
Jun 03 Python
Django用户认证系统如何实现自定义
Nov 12 Python
python+flask编写一个简单的登录接口
Nov 13 Python
查找适用于matplotlib的中文字体名称与实际文件名对应关系的方法
Jan 05 Python
解决import tensorflow导致jupyter内核死亡的问题
Feb 06 Python
浅析Python模块之间的相互引用问题
Feb 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 将图片按创建时间进行分类存储的实现代码
2010/01/05 PHP
php读取mysql中文数据出现乱码的解决方法
2013/08/16 PHP
Thinkphp中Create方法深入探究
2014/06/16 PHP
PHP扩展模块memcached长连接使用方法分析
2014/12/24 PHP
php实现在服务器端调整图片大小的方法
2015/06/16 PHP
php 三大特点:封装,继承,多态
2017/02/19 PHP
Aster vs Newbee BO5 第二场2.19
2021/03/10 DOTA
jQuery 遍历json数组的实现代码
2020/09/22 Javascript
jQuery实现鼠标滑过遮罩并高亮显示效果
2013/07/16 Javascript
jQuery中 prop() attr()使用详解
2015/05/19 Javascript
js数组如何添加json数据及js数组与json的区别
2015/10/27 Javascript
微信小程序 生命周期和页面的生命周期详细介绍
2017/01/19 Javascript
用javascript获取任意颜色的更亮或更暗颜色值示例代码
2017/07/21 Javascript
jQuery中将json数据显示到页面表格的方法
2018/05/27 jQuery
微信小程序实现同一页面取值的方法分析
2019/04/30 Javascript
vue history 模式打包部署在域名的二级目录的配置指南
2019/07/02 Javascript
JS事件流与事件处理程序实例分析
2019/08/16 Javascript
javascript实现贪吃蛇小练习
2020/07/05 Javascript
JS实现放大镜效果
2020/09/21 Javascript
Openlayers绘制地图标注
2020/09/28 Javascript
[01:09]DOTAPLUS——DOTA2的新时代
2018/04/04 DOTA
Python找出文件中使用率最高的汉字实例详解
2015/06/03 Python
flask中过滤器的使用详解
2018/08/01 Python
Python import与from import使用及区别介绍
2018/09/06 Python
解决python中遇到字典里key值为None的情况,取不出来的问题
2018/10/17 Python
jupyter 中文乱码设置编码格式 避免控制台输出的解决
2020/04/20 Python
Python接收手机短信的代码整理
2020/08/02 Python
python PyAUtoGUI库实现自动化控制鼠标键盘
2020/09/09 Python
德国最大的婴儿用品网上商店:Kidsroom.de(支持中文)
2020/09/02 全球购物
CAD制图设计师自荐信
2014/01/29 职场文书
班级文化标语
2014/06/23 职场文书
租房安全协议书
2014/08/20 职场文书
2016年大学生就业指导课心得体会
2015/10/09 职场文书
深度学习详解之初试机器学习
2021/04/14 Python
Android自定义双向滑动控件
2022/04/19 Java/Android
SpringBoot详解执行过程
2022/07/15 Java/Android