Python ORM框架SQLAlchemy学习笔记之关系映射实例


Posted in Python onJune 10, 2014

昨天简单介绍了SQLAlchemy的使用,但是没有能够涉及其最精彩的ORM部分,今天我将简单说明一下,当然主要还是讲解官方文档的内容,由于是学习笔记,有可能存在精简或者自己理解的部分,不做权威依据。

当我们开始使用ORM,一种可配置的结构可以用于描述我们的数据库表,稍后我们定义的类将会被映射到这些表上。当然现代的SQLAlchemy(新版本SQLAlchemy,原文是modern SQLAlchemy)使用Declarative把这两件事一起做了,即允许我们把创建类和描述定义数据库表以及它们之间的映射关系一次搞定。

这段话是什么意思呢?简单来说吧,SQLAlchemy分为Classic (经典模式)和Modern (现代模式),Classic定义数据库表的模式比较传统,需要先描述这个表。

1. Classic 映射

比如以官方文档中的例子,我们拥有表结构如下:

CREATE TABLE [users] (
  [id]       INTEGER PRIMARY KEY,
  [name]     TEXT NOT NULL,
  [fullname] TEXT NOT NULL,
  [password] TEXT NOT NULL
);

下面我们描述这张表:

from sqlalchemy import Table, MetaData, Column, Integer, Stringmetadata = MetaData()
user = Table('users', metadata,
            Column('id', Integer, primary_key=True),
            Column('name', String(50)),
            Column('fullname', String(50)),
            Column('password', String(12))
        )

好,这样我们的表算是描述完成了,接下来我们需要定义我们的Python类,比如这样的:
class User(object):
    def __init__(self, name, fullname, password):
        self.name = name
        self.fullname = fullname
        self.password = password

如何让我们定义的类与之前描述的表结构发生映射关系就是我们接下来要做的:
from sqlalchemy.orm import mapper
mapper(User, user)

大家注意到mapper函数,第一个参数是我们类的名称,第二个参数是我们先前描述的表定义。

这就是传统的定义ORM的方法,有关这个方法的更多信息,可以阅读文档Mapper Configuration,以后有机会再和大家详谈。

2. Modern 映射

当大家都乐此不疲的定义描述表,定义类,再映射来实现ORM的时候,SQLAlchemy团队搞出了更简单的映射方法,那就是Modern模式了,即通过定义映射类来一次性完成所有任务。

为了定义的类能够被SQLAlchemy管理,所以引入了Declarative这个概念,也就是说我们所有的类必须是Declarative基类的子类,而这个基类可以通过下面的办法来获取:

from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()

当然一个程序内,这个基类最好是唯一的,建议存储在全局变量比如Base中供所有映射类使用。

现在通过刚才的代码我们得到了名为Base的基类,通过这个基类我们可以定义N多的映射子类,而这些子类都能被SQLAlchemy Declarative系统管理到。

下面我们还是看刚才的那个users表的例子:

from sqlalchemy import Column, Integer, String
class User(Base):
     __tablename__ = 'users'     id = Column(Integer, primary_key=True)
     name = Column(String)
     fullname = Column(String)
     password = Column(String)
     def __init__(self, name, fullname, password):
         self.name = name
         self.fullname = fullname
         self.password = password
     def __repr__(self):
        return "<User('%s','%s', '%s')>" % (self.name, self.fullname, self.password)

就这段代码就完成了我们先前在Classic中需要的三步,代码比原先更简洁和容易管理了,同刚才Classic中Table定义的Column,这个代表数据库表中的列,当然Integer和String代表着数据库表的字段类型了。

这样User类就建立起与数据库表的映射,真实表的名字可以使用__tablename__指明,然后是表列的集合,包括id、name、fullname以及password,当然想必大家已经知道了,我们通过primary_key=True已经指明id为主键了。当然一些数据库表可能不包含有主键(例如视图View,当然视图也可以被映射),ORM为了能够实际映射表需要至少一个列被定义为主键列。多列,比如复合多主键也能够被很好地映射支持。

大家可能注意到User类中还包含有通常意义上的Python魔术方法,包含__init__()初始化类(构造方法)以及__repr__()字符串化支持方法,当然这些都是可选的,如果需要这个类可以加入程序所需要的任意多方法或者属性,你只要把这个类看作一个普通的Python类就可以了。

当然User类唯一不能马虎的就是必须继承至Base,这个Base就是刚才我们通过declarative_base()生成的类,通过它我们可以接下来让SQLAlchemy Declarative系统管理并操作这些映射类和数据库表。

实际上包括继承的Base类,所有的类都应该是Python的新式类(new style class),关于新式类的更多信息可以参考Python手册。

随着我们的User映射类通过Declarative系统构造成功,我们就拥有了相关的定义信息,比如在Classic定义中介绍的Table()描述,也包含映射到表的类,就是User自身,我们可以通过User.__table__来查看我们的表描述情况:

>>> User.__table__ 
Table('users', MetaData(None),
    Column('id', Integer(), table=<users>, primary_key=True, nullable=False),
    Column('name', String(), table=<users>),
    Column('fullname', String(), table=<users>),
    Column('password', String(), table=<users>), schema=None)

当然找到描述表的数据结构,也应该能找到mapper,我们的Mapper对象可以通过__mapper__属性来获取,比如这样的:
>>> User.__mapper__ 
<Mapper at 0x...; User>

同样的MetaData可以通过.metadata属性找到。

好啦,下面轻松一下,见证奇迹的时刻,我们需不需要定义创建好实体数据库然后再定义ORM?对于SQLAlchemy来说这些都是小事一桩,其都可以给你一手包办,也就是说你可以完全不必理会数据库,交给SQLAlchemy就可以了,比如通过MetaData.create_all()并将engine参数传入即可(什么是engine?参考我的笔记1),比如通过下面的方式创建我们的users表。

>>> Base.metadata.create_all(engine) 
PRAGMA table_info("users")
()
CREATE TABLE users (
    id INTEGER NOT NULL,
    name VARCHAR,
    fullname VARCHAR,
    password VARCHAR,
    PRIMARY KEY (id)
)
()
COMMIT

由于我们开启了engine的echo=True,所以在交互命令下SQLAlchemy把SQL语句也输出了,正好可以检验是否符合我们的要求。

这样简单的create_all()我们就轻松建立起先前ORM映射定义的表啦。

时间不早了,今天先聊到这儿,下次再谈SQLAlchemy的其他特性。

Python 相关文章推荐
Python实时获取cmd的输出
Dec 13 Python
Python中使用OpenCV库来进行简单的气象学遥感影像计算
Feb 19 Python
python snownlp情感分析简易demo(分享)
Jun 04 Python
Python标准模块--ContextManager上下文管理器的具体用法
Nov 27 Python
Python实现拷贝/删除文件夹的方法详解
Aug 29 Python
对python多线程SSH登录并发脚本详解
Feb 14 Python
Python嵌套式数据结构实例浅析
Mar 05 Python
分析经典Python开发工程师面试题
Apr 08 Python
Python静态类型检查新工具之pyright 使用指南
Apr 26 Python
详解python实现数据归一化处理的方式:(0,1)标准化
Jul 17 Python
Python实现直播推流效果
Nov 26 Python
pandas使用函数批量处理数据(map、apply、applymap)
Nov 27 Python
Python ORM框架SQLAlchemy学习笔记之安装和简单查询实例
Jun 10 #Python
Python使用htpasswd实现基本认证授权的例子
Jun 10 #Python
python网络编程学习笔记(10):webpy框架
Jun 09 #Python
python网络编程学习笔记(九):数据库客户端 DB-API
Jun 09 #Python
python网络编程学习笔记(八):XML生成与解析(DOM、ElementTree)
Jun 09 #Python
python网络编程学习笔记(七):HTML和XHTML解析(HTMLParser、BeautifulSoup)
Jun 09 #Python
python网络编程学习笔记(六):Web客户端访问
Jun 09 #Python
You might like
玩转虚拟域名◎+ .
2006/10/09 PHP
解析curl提交GET,POST,Cookie的简单方法
2013/06/29 PHP
PHP5.5在windows安装使用memcached服务端的方法
2014/04/16 PHP
PHP中对数组的一些常用的增、删、插操作函数总结
2015/11/27 PHP
java解析json方法总结
2019/05/16 PHP
PHP实现随机发扑克牌
2020/04/22 PHP
js 手机号码合法性验证代码集合
2012/09/29 Javascript
解决JS浮点数运算出现Bug的方法
2013/03/12 Javascript
Jquery easyui 下loaing效果示例代码
2013/08/12 Javascript
jQuery多级弹出菜单插件ZoneMenu
2014/12/18 Javascript
jQuery获得子元素个数的方法
2015/04/14 Javascript
javascript关于open.window子页面执行完成后刷新父页面的问题分析
2015/04/27 Javascript
javascript实现在网页中运行本地程序的方法
2016/02/03 Javascript
vue mint-ui 实现省市区街道4级联动示例(仿淘宝京东收货地址4级联动)
2017/10/16 Javascript
基于vue2实现上拉加载功能
2017/11/28 Javascript
JS设计模式之状态模式概念与用法分析
2018/02/05 Javascript
利用CDN加速react webpack打包后的文件详解
2018/02/22 Javascript
jQuery分组选择器简单用法示例
2019/04/04 jQuery
vue.js实现图书管理功能
2019/09/24 Javascript
如何正确理解vue中的key详解
2019/11/02 Javascript
vue(2.x,3.0)配置跨域代理
2019/11/27 Javascript
Vue的状态管理vuex使用方法详解
2020/02/05 Javascript
python设置环境变量的作用和实例
2019/07/09 Python
详细整理python 字符串(str)与列表(list)以及数组(array)之间的转换方法
2019/08/30 Python
python实现简单坦克大战
2020/03/27 Python
Python如何给你的程序做性能测试
2020/07/29 Python
美国面料纺织品商城:Fabric.com
2017/06/28 全球购物
新加坡交友网站:be2新加坡
2019/04/10 全球购物
莫斯科隐形眼镜网上商店:Linzi
2019/07/22 全球购物
意大利时尚奢侈品店:D’Aniello Boutique
2021/01/19 全球购物
Java面试题:请问一下代码输出是什么
2015/05/27 面试题
医学专业大学生求职信
2014/07/12 职场文书
党员干部群众路线教育实践活动个人对照检查材料
2014/09/23 职场文书
2014年党员个人工作总结
2014/12/02 职场文书
2016年世界人口日宣传活动总结
2016/04/05 职场文书
Android移动应用开发指南之六种布局详解
2022/09/23 Java/Android