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

简介:

1. 如何在Django外使用它的ORM

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

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

import os
os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'

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

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

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

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

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

# -*- coding: utf-8 -*-

import os

os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
from django.db import connections

class BaseHandler(tornado.web.RequestHandler):
    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() 本身也是不需要的。我们应该把代码作一些修改:

# -*- coding: utf-8 -*-

import os

os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
from django.db import connections

class BaseHandler(tornado.web.RequestHandler):
    def finish(self, *args, **kargs):
        for c in connections.all():
            try:
                c._commit()
            except:
                pass

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()

def initialize(self):
    for c in connections.all():
        try:
            c._commit()
        except:
            pass

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


目录
相关文章
|
9月前
|
SQL 安全 数据库
如何在Django中正确使用参数化查询或ORM来避免SQL注入漏洞?
如何在Django中正确使用参数化查询或ORM来避免SQL注入漏洞?
518 77
|
9月前
|
SQL 安全 数据库连接
除了使用Django的ORM,还能通过什么方式在Django中避免SQL注入漏洞?
除了使用Django的ORM,还能通过什么方式在Django中避免SQL注入漏洞?
218 73
|
10月前
|
SQL 定位技术 数据库
深入探索Django ORM:高效数据库操作的秘诀####
本文旨在为读者揭开Django ORM(对象关系映射)的神秘面纱,通过一系列生动的比喻和详实的案例,深入浅出地讲解其核心概念、工作原理及高级特性。我们将一起探讨如何利用Django ORM简化数据库交互,提升开发效率,同时确保数据的一致性和安全性。不同于传统的技术文档,本文将以故事化的形式,带领读者在轻松愉快的氛围中掌握Django ORM的精髓。 ####
|
11月前
|
SQL 监控 数据库
深入探索Django ORM:高效数据操作的秘诀与实践####
在当今的Web开发领域,提升数据访问层的效率是优化应用性能的关键。本文旨在通过剖析Django框架中的ORM(对象关系映射)机制,揭示其如何简化数据库交互,并探讨一系列高级技巧与策略,帮助开发者构建更高效、可维护的数据访问代码。我们不涉及安装步骤或基础概念,而是聚焦于实战经验分享,旨在为中高级开发者提供深度洞见。 ####
|
12月前
|
SQL Go 数据库
【速存】深入理解Django ORM:编写高效的数据库查询
【速存】深入理解Django ORM:编写高效的数据库查询
251 0
|
数据库 Python
Django ORM
【8月更文挑战第23天】
121 4
|
数据管理 数据挖掘 调度
Django后端架构开发:URLconf到ORM深度剖析
Django后端架构开发:URLconf到ORM深度剖析
151 1
|
API 数据库 开发者
【独家揭秘】Django ORM高手秘籍:如何玩转数据模型与数据库交互的艺术?
【8月更文挑战第31天】本文通过具体示例详细介绍了Django ORM的使用方法,包括数据模型设计与数据库操作的最佳实践。从创建应用和定义模型开始,逐步演示了查询、创建、更新和删除数据的全过程,并展示了关联查询与过滤的技巧,帮助开发者更高效地利用Django ORM构建和维护Web应用。通过这些基础概念和实践技巧,读者可以更好地掌握Django ORM,提升开发效率。
174 0
|
SQL 缓存 数据库
Django中ORM性能调优
【6月更文挑战第19天】 1. **索引优化**:使用`db_index=True`为模型字段创建索引,提升查询速度。 2. **批量操作**:批量创建和更新,减少数据库交互。 3. **查询优化**:利用`select_related`和`prefetch_related`减少查询次数。 4. **缓存**:使用内置缓存或Redis减少数据库访问。 5. **异步任务**:用Celery处理耗时操作,提高响应速度。 6. **数据库连接池**:管理连接,减少创建和销毁开销。 7. **SQL直接操作**:在必要时用原生SQL,避免ORM性能瓶颈。 8. **分页查询**:减少数据传输,改善用
185 10
|
SQL Go 数据库
Django入门到放弃之ORM多表操作
Django入门到放弃之ORM多表操作