Django 1.6 Models (V) — Raw SQL

这一节是讲如何使用原始 SQL 在 django 框架下进行数据库查询,使用 raw sql 有两种基本的模式:Manager.raw() 以及 纯粹的 sql 脚本执行。使用 raw sql 进行查询可以处理一些特殊的情形。

一般情况下不推荐使用,理由如下:

  1. 需要特别小心 sql 注入攻击;
  2. 可能会破坏 Models 层的一些潜在关系;
  3. 使得逻辑可能会依赖于数据库实现;

一、Manager.raw() 方法与 RawQuerySet

与前面的类似,通过 raw sql 进行查询会返回一个 RawQuerySet 对象;注意 raw 方法是要在 manager(而不是 QuerySet)上面进行调用,输入一个 sql 脚本,以及一个参数列表(list 或者 dict,可选),即可返回这个 RawQuerySet;

经过实验,这个 RawQuerySet 功能非常有限,首先元素的提取只能够通过下标或者迭代,其次提取出来的每个元素(实际上是行)也并真的是一个 Model 对象。

我们可以通过下面这样的方法来构造 Model,用一种映射的方法来指定 Model 的字段值。

>>> name_map = {'first': 'first_name', 'last': 'last_name', 'bd': 'birth_date', 'pk': 'id'}
>>> Person.objects.raw('SELECT * FROM some_other_table', translations=name_map

这种方式就可以构造一个特殊的 model 对象,具体用的时候还需要好好测试一下。

貌似 RawQuerySet 只管到里面的 id 以及有限的指定字段,而且这些字段是可以指定别名的。

所以其实 RawQuerySet 这种通过 Manager.raw() 方法提取的还是不很直观。

二、通过 connection 对象直接执行 sql 查询

简要说明一下步骤,直接看一下例子就懂了:

from django.db import connection

def my_custom_sql(self):
    cursor = connection.cursor()
    cursor.execute("UPDATE bar SET foo = 1 WHERE baz = %s", [self.baz])
    cursor.execute("SELECT foo FROM bar WHERE baz = %s", [self.baz])
    row = cursor.fetchone()
    return row

也就是说,在 django.db 空间里面引入 connection 对象,然后通过 connection.cursor 创建一个 cursor <class 'django.db.backends.util.CursorDebugWrapper'> 对象,通过 cursor.execute(script[, params]) 来执行一个查询。

注意提交的参数一定不要直接通过 format string 放到脚本里面,而要通过 execute 的第二个参数列表进去,这样 django 引擎会自动防止脚本注入。

调用了 execute 之后,结果集就可以在 cursor 之上获取了,通过 cursor.fetchone 或者 cursor.fetchall 来获取结果集。结果集的每一行是一个 tuple,如果是 fetchall 的话就会返回一个 tuple 的 list。


【转载请附】愿以此功德,回向 >>

原文链接:https://www.huangwenchao.com.cn/2014/05/django-models-5.html【Django 1.6 Models (V) — Raw SQL】

发表评论

电子邮件地址不会被公开。 必填项已用*标注