zl程序教程

您现在的位置是:首页 >  后端

当前栏目

在Tornado中使用Django的ORM的注意事项

django 注意事项 ORM Tornado 使用
2023-09-14 09:02:06 时间
1. 如何在Django外使用它的ORM

Django 的 ORM 虽然功能和性能都不怎么样,但重在简单方便,更重要的是,已经熟悉使用它了。

要在 Django 外使用它的 ORM ,最简单的办法,就是设置一个DJANGO_SETTINGS_MODULE 的环境变量就可以了:


当然,如果你要是喜欢折腾,也可以从 django.conf 中把 settings 引入,然后使用configure 方法去配置它的 DATABASES。

2. Django环境和Tornado的不同之处

能正确使用 Django 的 API 不代表就万事大吉,它的 ORM 是给自己量身订做的,换到另外一个环境中去,适配的问题只能我们自己解决。

Django 是传统的 Web 运行方式,一个请求过来,就开一个新的“进程/线程”去处理它,在数据库的连接处理上:

在需要进行数据库操作时,才去处理与数据库的连接。 因为是传统的 Web 运行方式,所以,每个请求都会使用单独的数据库连接。 连接一旦创建,那么直到当前请求结束,此连接才会关闭。此请求中的接下来的数据库操作会共用连接。 每次数据库操作时,都会去获取一次 cursor ,此时,会判断连接的可用性。所以,不用担心所谓的“8小时问题”,对于 MySQL 来说,它使用 ping() 方法判断连接的可用性。 请求处理完时, Django 会确保连接关闭。

搞清楚 Django 对数据库连接的处理方式,就好办了。

Tornado 的运行方式是单进程的,同时, Tornado 中的 请求 显然与 Django 中的 请求 不是一个东西,那么 Django 的 ORM 机制,不会知道 Tornado 中一个请求什么时候结束。而 Tornado 又是单进程方式,所以,如果你什么都不做,那么结果就是, Tornado 打开一个与数据库的连接,永远不关闭,请求之间也共用这个连接。

看到这里,可以看到,在 Tornado 中要做一个连接池是多少简单的事,当然,除非和数据库的交互支持异步调用的方式,否则永远只能使用一个数据库连接,没连接池什么事。

3. Tornado中要做的事

如果你什么也不做,初看起来,数据库工作得很好, Tornado 自己的数据库封装中面临的“8小时问题”对 Django 的 ORM 来说是不存的,因为它每次获取 cursor 时都会判断连接的可用性。

不过你需要解决的另外一个问题是事务提交。

Tornado 在自己的 MySQL 封装中,使用了 connect.autocommit(True),而 Django 的 ORM 默认是没有打开 autocommit 的。所以,你会看到的一个现象就是,对于 InnoDB 引擎, Tornado 跑起来之后,另外一个客户端对数据库的修改(比如添加了一个记录),在 Tornado 之中是不可见的。你要么打开 autocommit ,要么手动 commit ,我觉得手动 commit 比较好,在每次请求结束时:


def finish(self, *args, **kargs): [c.connection and c.connection.commit() for c in connections.all()]

另外要注意的一点是,在 Tornado 中最好不要使用 Django 的@transaction.commit_on_success 这类全局性的东西,除非你真的清楚它对整个处理流程有怎样的影响。

4. 2012-7-15更新

在 finish() 中直接 commit() 有一个问题——虽然 Django 自己在执行数据库操作时会确保数据库的连接已经成功建立,但是,在调用 finish() 之前可能根本就没有任何的数据库操作。这时直接使用 commit() 时可能连接已经失效了(但是连接它还存在,即不为 None),于是就会抛出异常。当然,如果之前没有任何的数据库操作, commit() 本身也是不需要的。我们应该把代码作一些修改:


5. 2012-8-15更新

对于 InnoDB 而言, Select 这类读操作也是受事务隔离影响的(参考:http://www.cnblogs.com/shiyangxt/archive/2009/02/11/1388519.html)。简单说,另外的事务已经 commit 的数据,对处于旧事务中的 Select 也是不可见的。

这里有一个很大的影响,就是前面我们在 finish() 中确保执行了 commit(),通常情况下,一个新的请求过来,是处于一个全新的事务当中。但是,如果在 Tornado 当中有一些 callback ,在新请求过来之前就访问了数据库,即打开了一个新的事务,而这些内部的 callback 又不会去调用finish() 。于是,新的请求就可能处于一个‘旧’的事务当中,这时做 Select 就可能找不到一些数据。所以,为了确保新的请求处于新的事务当中,以保证 Select 操作的正确,我们在initialize() 也需要做一遍 commit():


这样我们也只能保证“请求”的事务是新的。对于其它非请求时的数据库访问,比如写的一些定时器类的功能,在查库之前,也需要做一遍 commit() 以保证从数据库取出来的数据是有效的。


Django ORM Model的基本查询操作API 1.创建Model实例对象 阅读文本前请参考此文章的数据表结构 使用save方法创建Model实例: 由于Topic需要一个User对象,所以,先获取username是admin(超级用户)的User对象,再去创建Topic对象
Django ORM 聚合查询和分组查询 对QuerySet计算统计值,需要使用aggregate方法,提供的参数可以是一个或多个聚合函数 Django提供了一系列的聚合函数,其中Avg(平均值)、Count(计数)、Max(最大值)、Min(最小值)、Sum(加和)最为常用 要使用这些聚合函数,需要将它们引入当前的环境中:
Django ORM F对象和Q对象查询 F对象用于操作数据库中某一列的值,它可以在没有实际访问数据库获取数据值的情况下对字段的值进行引用 使用F对象之前需要将它引入当前的环境中:
Django ORM基本应用与原理剖析 1.ORM构建数据表 由于每一个数据表对应一个Model定义,每一个Model都是一个Python类,所以,Model之间是可以继承的。Django规定,所有的Model都必须继承自django.db.models.Model
因为 Django ORM update,我今天差点「从删库到跑路」 经过周末两天回血,今天早早来到公司,准备把上周遗留的 BUG 修了,然后再多写几个 BUG。 还没等我把双肩包放好,就看见群里有同事反馈,有一个表的数据没了。