爱上 SQLAlchemy 的 10 个理由(转)

时间:2023-02-23 07:50:15

原文:http://python.jobbole.com/82453/

本文由 伯乐在线 - Namco 翻译,唐尤华 校稿。未经许可,禁止转载!
英文出处:Paul Johnston。欢迎加入翻译组

最近,我见到了很多针对 ORM 的抨击,但是我觉得有些批评是莫须有的。我本人就是 SQLAlchemy 的忠实拥趸。在我的项目里很多地方都用到了 SQLAlchemy,我也为 SQLAlchemy 项目贡献了一些代码。这篇文章里我会阐述你应当爱上 SQLAlchemy 的10个理由。说实话,除了 SQLAlchemy 以外还有很多优秀的 ORM,我所阐述的大部分理由同样适用于它们但是 SQLAlchemy 是我的最爱。

1、用应用程序代码定义数据库模式

SQLAlchemy 允许你使用 Python 代码来定义数据库模式(schema)。下面是一个电子商务网站的例子,一个订单就代表一条记录。

Python
 
1
2
3
4
5
class OrderItem(Base):
    id = Column(Integer, primary_key=True)
    order = many_to_one('Order')
    product = many_to_one('Product')
    quantity = Column(Integer)

定义数据库模式的 Python 代码在 SQLAlchemy 中叫做模型(model)。因为这些模型都是用 Python 的类实现的,所以你可以添加自己的类方法。这样可以把相关功能放在一起方便维护。

Python
 
1
2
3
4
5
class Order(Base):
    ...
    def update_stock(self):
        for item in self.items:
            item.product.stock -= item.quantity

上面这个例子说明了在 SQLAlchemy 中数据库的模式也可以通过版本控制来维护。所以使用SQLAlchemy 的同时,你也可以享受到版本控制的诸多便利:比如版本追踪、标签、追溯(blame)等等。

2、自动同步模型到数据库模式

Alembic 是 SQLAlchemy 的一个数据库管理插件。当你修改模型的时候,Alembic 可以自动更新数据库模式。使用 Alembic 来做一些添加表或者列的小改动是非常便捷快速的。

Python
 
1
2
3
4
$ alembic upgrade head
INFO  [alembic.context] Context class PostgresqlContext.
INFO  [alembic.context] Will assume transactional DDL.
INFO  [alembic.context] Running upgrade None -> 1975ea83b712

尽管在开发环境中自动同步非常方便,但是大多数人还是想在生产环境中采用更稳妥一些的方式。这一点 Alembic 也想到了,它可以自动生成修改的脚本,数据库管理员可以在检视脚本之后再应用到生产环境的数据库上。

3、Pythonic 的代码风格让你的代码更易读

SQLAlchemy 使用更 Pythonic 的方式表示数据库关系,这对于阅读和编写代码来说是非常方便的。我们来看下面这个例子,这个例子可以打印出在一个订单中的所有产品。

Python
 
1
2
for item in order.items:
    print(item.product.name, item.quantity)

代码非常的简单易读,但是打通了两个数据库,执行了 JOIN 连接查询。order.items 是一对多的关系,SQLAlchemy 会自动加载 OrderItem 中和这个订单相关的对象。item.product 则储存的是多对一的关系,SQLAlchemy 会自动加载对应的产品。

SQLAlchemy 也可以运用类。如果应用修改了一个有映射的字段,对象会自动请求写入数据库。这个功能使编写应用逻辑的时候没有了后顾之忧。

4、用 Python 构建查询语句

类似用主键获取对象这种简单查询只需要很少的代码:

Python
 
1
order = session.query(Order).get(order_id)

使用 Python 的查询语法,我们可以实现更复杂的查询。比如下面的例子,我要查找两天以前的有效订单:

Python
 
1
2
overdue_orders = session.query(Order).filter(Order.status == 'active'
            && Order.time < datetime.now() - timedelta(days=2))

SQLAlchemy 的语法可以让你把 SQL 语句和 Python 的变量结合起来,并且可以杜绝 SQL 注入攻击。SQLAlchemy 会在内部重载各种比较运算符,然后将它们转换成 SQL 语句。

当你执行一条非常复杂的查询时,使用 SQLAlchemy 语法来定义查询也是可以的。但是我认为 SQLAlchemy 可以胜任的查询复杂程度是有限的,某些时候直接写 SQL 语句可能更容易些。在这种情况下,你可以定义数据库视图来完成复杂查询,SQLAlchemy 可以把视图映射到 Python 对象。

5、与 Web 框架的无缝集成

有些框架默认支持SQLALchemy ,比如说 Pyramid。对于其他 web 框架,你需要安装一个集成库来支持 SQLAlchemy,比如说用于 Flask 的 Flask-SQLAlchemy 或者用于 Django 的 aldjemy。

SQLAlchemy 会维持一个连接池,为每一个 web 请求提供一个可用的数据库连接。那些支持库可以处理常见异常,提高应用的健壮性,让应用在某些异常情况下不至于崩溃,比如运行时重启数据库这样的操作。

每一个请求都会用事务包裹起来,如果请求成功就提交事务,否则就回滚。这种设计使得外部方法能够正确地与数据库交互,而不需要关心具体的数据库处理代码。

6、预先加载提高性能

大部分 ORM 都使用的是延迟加载策略。在第一次调用关系时,一次 SQL 查询会执行,加载数据。像上面的例子,order.items 的调用实际上执行了一次 SQL 查询,之后的每次使用 item.product 都会发起另外的查询。因为 item.product 是在一个循环中调用的,所以会生成大量的 SQL 查询,导致性能降低。这种情况叫做“n+1 选择问题”。

SQLAlchemy 针对上述问题有一个解决方案:预先加载(eager loading)。当我们第一次加载 Order 这个对象时,我们可以通知 SQLAlchemy 我们会使用那些关系,然后 SQLAlchemy 就能在一次查询中加载所有数据,语法如下所示:

Python
 
1
session.query(Order).options(joinedload_all('items.product')).get(order_id)

7、透明的多态支持

像 Python 这样的面向对象语言是鼓励使用多态的。如果有一个 Person 的基类,我们就可以基于 Person 来创建子类,比如 增加了新字段的Employee 或者 Customer 类。但是传统的 SQL 数据库不支持多态,所以 ORM 想要支持多态也是有心无力。

但是 SQLAlchemy 在 SQL 中完美地模拟了多态。我们在 Python 代码中可以非常自然地使用多态,数据库中的数据也可以通过 SQL 便捷地获取。在应用代码中我们可以轻松地使用多态类,而不需要关心它们究竟是怎么存储的。

8、兼容已有数据库

一些 ORM 要求你的数据库结构满足既定条件,强制每张表都有单一主键列,甚至主键名称必须是 “id”。如果你从头建立一个数据库,这些限制并不是问题。但是如果你想用以前的数据库,这些限制条件会阻止你访问那些不满足条件的表。

SQLAlchemy 不会假定你的数据库结构,所以可以完美支持以前的数据库。还有一个叫做 sqlacodegen 的工具可以根据已有的数据库生成 SQLAlchemy 模型。SQLAlchemy 使得你可以通过简单的 Python 脚本和以前的数据库进行交互。

9、提供许多钩子函数让你自定义库

SQLAlchemy 拥有清晰的分层架构。几乎任何 SQLAlchemy 库都可以被重写以满足特定需求。

当在有多个使用者的云应用上工作的时候,我发现了一个非常有用的功能。比如说应用中大多数查询都包含了过滤条件,只返回当前使用者的结果。就像下面这个例子:

Python
 
1
products = session.query(Product).filter(Product.merchant == current_user.merchant).all()

但是我发现,如果一不小心忘记加过滤条件的话,可能让某个用户可以看到其他经销商的信息,而这是不允许的。谨慎起见,我们可以创建一个自定义的 SQLAlchemy 的 session 工厂函数,可以在会话中自动给所有查询应用过滤条件。虽然只是这么一点小小的控制代码,却可以让你的应用安全系数更高。

10、完善的文档

有些开源项目的文档的确是漏洞百出,但是 SQLAlchemy 不是这样。SQLAlchemy 的文档非常详尽,并且还有从简单例子到高级特性的学习指南,以及全面的 API 参考文档。这对于开发人员学习和使用 SQLAlchemy 是非常有帮助的。

爱上 SQLAlchemy 的 10 个理由(转)的更多相关文章

  1. 10 个理由让你继续干 IT

    1.钱,钱,钱 对,我们努力工作就是为了赚钱,而IT专业人士的努力工作的确得到了很好的补偿.报酬不仅仅是好而已,而是非常棒.根据美国劳工部<2010年美国 就业与报酬情况概览>(表6,PD ...

  2. 高校应该使用 Drupal 的10大理由

    使用 Drupal 已经成为全球顶尖高校中的一种潮流,它已经被全球数以百计的院校选择并应用,无论是哈佛.斯坦福.杜克.布朗.罗格斯.剑桥.耶鲁还是其它众多知名高校,都已经选择 Drupal 作为它们理 ...

  3. 使用 FreeMarker 替换 JSP 的 10 个理由

    你还在使用 Java 服务器页面(俗称JSP)吗?我曾经也是,但是几年前我抛弃了它们,并且再也没有用过JSP了.JSP 是个很好的概念,但是它却剥夺了 web 开发的乐趣. 对我而言,这些都是小事,比 ...

  4. 爱上一门语言不需要理由——我的js之路

    开始记录js学习:~~~~分享一下你的js学习途径吧 决定学习前端之后,开始接触JavaScript 1995年,网景公司的Brendan Eich用10天完成了JavaScript的设计,他被称为J ...

  5. 推荐:7 月份值得一看的 Java 技术干货!

    月底了,又到了我们总结这一个月 Java 技术干货的时候了,又到了我们给粉丝免费送书的日子了. 7 月份干货总结 Oracle 发布了一个全栈虚拟机 GraalVM 一文带你深入拆解 Java 虚拟机 ...

  6. 2019 最新 Java 核心技术教程,都在这了!

    Java技术栈 www.javastack.cn 优秀的Java技术公众号 以下是Java技术栈微信公众号发布的所有关于 Java 的技术干货,会从以下几个方面汇总,本文会长期更新. Java 基础篇 ...

  7. Java 核心编程技术干货,2019 最新整理版!

    Java技术栈 www.javastack.cn 优秀的Java技术公众号 以下是Java技术栈微信公众号发布的所有关于 Java 的技术干货,会从以下几个方面汇总,本文会长期更新. Java 基础篇 ...

  8. 最新App Store审核10大被拒理由

    最近,苹果在官网给出了截至2015年2月份应用被拒绝的十大理由,其中50%以上的应用被拒绝都是因为这10个原因,其中7个理由和2014年相同,其中排名前三的原因分别是:需要补充更多信息.存在明显的bu ...

  9. 最新App Store审核指南与10大被拒理由

    最近,苹果在官网给出了截至2015年2月份应用被拒绝的十大理由,其中50%以上的应用被拒绝都是因为这10个原因,其中7个理由和2014年相同,其中排名前三的原因分别是:需要补充更多信息.存在明显的bu ...

随机推荐

  1. 关于SSH的一些tricks

    改善SSH登录速度 登录慢的原因有很多, 慢的症状也很多, 有些是出login慢, 有些是出password慢, 有些是输入完password后进提示符慢, 根据 http://superuser.c ...

  2. webservice发布服务:AXIS2及客户端调用

    1.Axis2: 到官网下载axis2的压缩包. 解压后: 1.将lib文件下的jar包复制到项目中 2.在web-inf下创建services->META-INF->services.x ...

  3. GEOS库学习之三:空间关系、DE-9IM和谓词

    要判断两个多边形的关系,实际上属于几何图形空间关系判断.几何图形并不只有多边形一种,它包括点.线.面构成的任何图形,两两之间相互关系也有很多种,因此空间关系非常复杂.根据前人的研究,总结出了DE-9I ...

  4. 2&period;2 编程之美--不要被阶乘吓到&lbrack;zero count of N factorial&rsqb;

    [本文链接] http://www.cnblogs.com/hellogiser/p/zero-count-of-N-factorial.html [题目] 问题1:‍给定一个整数N,那么N的阶乘N! ...

  5. 九度OJ1172--哈夫曼树

    哈夫曼树,第一行输入一个数n,表示叶结点的个数.需要用这些叶结点生成哈夫曼树,根据哈夫曼树的概念,这些结点有权值,即weight,题目需要输出所有结点的值与权值的乘积之和. 输入: 输入有多组数据.每 ...

  6. Apache &amp&semi; WebDav 配置(一)

    (一)简单Apache服务器的搭建!用于文件de上传.下载.修改.删除! ---------- - Apache 1. 使用最广的 Web 服务器.支持各种脚本(PHP)的执行 2. Mac自带,只需 ...

  7. python线程Example

    # -*- coding:utf-8 -*- import time import pymongo from threading import Thread from Queue import Que ...

  8. VMWare虚拟机启动报错物理内存不足

    尝试了三种修改 1.说是微软补丁KB2995388冲突-->>失败 2.修改win8.1高级环境性能更改设置-->>失败 3.修改config.ini文件-->>成 ...

  9. Echarts---柱状图实现

    做Echarts很简单,可以参看官网 http://echarts.baidu.com/index.html 作为程序员我们只需要把静态数据替换成我们自己需要的! 下面看一个自己做的例子: 还是先看看 ...

  10. Linux学习历程——Centos 7 uptime 、free命令

    一.命令介绍 uptime命令 uptime命令用于查看系统负载信息以及系统运行时间等. free命令 free命令用于查看当前系统中内存使用量信息. 二.实例 uptime命令实例 直接运行 upt ...