extra()方法

结果集修改器,一种提供额外查询参数的机制

使用extra:
1:Book.objects.filter(publisher__name='广东人员出版社').extra(where=['price>50'])
Book.objects.filter(publisher__name='广东人员出版社',price__gt=50)
2:Book.objects.extra(select={'count':'select count(*) from hello_Book'})

raw()方法

示例

使用raw:
Book.objects.raw('select * from hello_Book')
自定义sql:
Book.objects.raw("insert into hello_author(name) values('测试')")
rawQuerySet为惰性查询,只有在使用时生会真正执行

执行原始查询

管理器的 raw() 方法可以用于执行原始 SQL 并返回模型实例:

Manager.raw(raw_query, params=None, translations=None)

这个方法执行一个原始 SQL 查询并返回一个 RawQuerySet 实例。这个 RawQuerySet 实例是可迭代的,就象通常的查询集一样可以提供对象实例。

来个例子就容易明白了,假设你有下面的模型:

class Person(models.Model):
first_name = models.CharField(...)
last_name = models.CharField(...)
birth_date = models.DateField(...)

你可以象这样执行定制的 SQL

>>> for p in Person.objects.raw('SELECT * FROM myapp_person'):
... print p
John Smith
Jane Jones

当然这个例子不是十分有趣,只是相当于运行了 Person.objects.all() 。但是, raw() 有一大把的相当给力的参数。

模型表名称

上例中 Person 表的名称是什么?

缺省情况下, Django 把模型的“应用标签”(你在 manage.py startapp 中使用的名称)和模型的类名称用下划线连接起来作为一个数据库表名。在上例中,我们假设 Person 模型在名称 myapp 的应用中,所以它的表名是 myapp_person

详情参见 db_table 选项的文档。这个选项还可以让你手动指定数据库表名。

Warning

传递给 .raw() 的 SQL 语句是不经过 Django 查验的。 Django 会指望从数据库中返回一组行,但这不是强迫性的。如果查询没有返回行,那么可以会产生一个(可能是隐性的)错误。

映射查询字段到模型字段

raw() 自动映射查询中的字段到模型字段。

查询中字段的顺序是无所谓的。亦即下面两句话是一样的:

>>> Person.objects.raw('SELECT id, first_name, last_name, birth_date FROM myapp_person')
...
>>> Person.objects.raw('SELECT last_name, birth_date, first_name, id FROM myapp_person')
...

映射是根据名字进行的。你可以使用 SQL 的 AS 子句来进行映射,因此如果你有一些其他包含 Person 数据的表,那么可以轻易地与 Person 实例相映射:

>>> Person.objects.raw('''SELECT first AS first_name,
... last AS last_name,
... bd AS birth_date,
... pk as id,
... FROM some_other_table''')

当名称一致时,模型实例就会正确创建。

还有一种方法,你可以使用 raw()translations 参数来进行映射。这个参数是一个映射查询字段名称和模型字段名称的字典。上述的查询也可以写成:

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

索引查找

raw() 支持索引,因此如果你只需要第一个结果,可以这样:

>>> first_person = Person.objects.raw('SELECT * from myapp_person')[0]

但是,索引和切片不是在数据库级别执行的。如果你在数据库中有大量的 Person 对象,那么在 SQL 级别来限制查询更有效率:

>>> first_person = Person.objects.raw('SELECT * from myapp_person LIMIT 1')[0]

延迟模型字段

字段也可以是不完全的:

>>> people = Person.objects.raw('SELECT id, first_name FROM myapp_person')

本例中查询返回的 Person 对象将会是延迟模型实例( (参见 defer() )。也就是说在查询中省略的字段会在需要是载入。例如:

>>> for p in Person.objects.raw('SELECT id, first_name FROM myapp_person'):
... print p.first_name, # This will be retrieved by the original query
... print p.last_name # This will be retrieved on demand
...
John Smith
Jane Jones

从表面看,好像查询同时获取了名和姓。但是,这个例子实际发出了三个查询。原始查询只获取了名,而两个姓是在打印时分别获取的。

唯一不能省略的字段是主键。 Django 使用主键来判别模型实例,所以在一个原始查询中必须包含主键,否则会抛出一个 InvalidQuery 异常。

加入统计

你也可以执行包含模型中没有的字段的查询。例如,我们可以使用 PostgreSQL 的 age() 函数 来让数据库统计出人员的年龄:

>>> people = Person.objects.raw('SELECT *, age(birth_date) AS age FROM myapp_person')
>>> for p in people:
... print "%s is %s." % (p.first_name, p.age)
John is 37.
Jane is 42.
...

raw() 传递参数

如果你需要执行带参数的查询,你可以使用 params 参数:

>>> lname = 'Doe'
>>> Person.objects.raw('SELECT * FROM myapp_person WHERE last_name = %s', [lname])

params 是一个参数列表。在查询字符串中你要使用 %s 占位符(不管你用何种数据库引擎)。占位符会被 params 列表中的参数代替。

Warning

不要在原始查询中使用格式化字符串!

你可能将上文的查询写成这样:

>>> query = 'SELECT * FROM myapp_person WHERE last_name = %s' % lname
>>> Person.objects.raw(query)

千万不要这样做。

使用 params 列表可以保护你避开 SQL 注入攻击 (通过漏洞把恶意 SQL 注入你的数据库)。如果你使用了字符串插入,那么尽早你会成为 SQL 注入的受害者,因此请谨记使用 params 列表。

执行自定义SQL

(
这种方式完全不依赖model,前两种还是要依赖于model;直接执行自定义SQL,这种方式可以完全避免数据模型,而是直接执行原始的SQL语句。
)

示例

执行自定义sql:
from django.db import connection
cursor=connection.cursor()
#插入操作
cursor.execute("insert into hello_author(name) values('郭敬明')")
#更新操作
cursor.execute('update hello_author set name='abc' where name='bcd'')
#删除操作
cursor.execute('delete from hello_author where name='abc'')
#查询操作
cursor.execute('select * from hello_author')
raw=cursor.fetchone() #返回结果行游标直读向前,读取一条
cursor.fetchall() #读取所有

扩展

有时候,甚至  Manager.raw() 还是不够用:你可能需要执行不明确对应模型的查询或者直接执行 UPDATE 、  INSERT 或 DELETE 查询。
在这种情况下,你可以直接操作数据库,完全绕开模型层。

django.db.connection 对象表现缺省数据库连接, django.db.transaction 表现缺省数据库事务。要使用数据库连接可以调用 connection.cursor() 来得到一个指针对象。然后,就可以调用 cursor.execute(sql,  [params]) 来执行 SQL 和 cursor.fetchone() 或 cursor.fetchall() 来返回结果行。在执行一个改变数据的操作后,你应当调用 transaction.commit_unless_managed() 来确保你的改变被提交。如果只是获取数据就不必提交了。例如:

def my_custom_sql():
from django.db import connection, transaction
cursor = connection.cursor() # Data modifying operation - commit required
cursor.execute("UPDATE bar SET foo = 1 WHERE baz = %s", [self.baz])
transaction.commit_unless_managed() # Data retrieval operation - no commit required
cursor.execute("SELECT foo FROM bar WHERE baz = %s", [self.baz])
row = cursor.fetchone()
return row

如果你使用多个数据库,那么可以使用 django.db.connections 来获得指定数据库的连接(和指针)。 django.db.connections 是一个类似字典的对象,允许你通过别名来获得指定数据库的连接:

from django.db import connections
cursor = connections['my_db_alias'].cursor()
# Your code here...
transaction.commit_unless_managed(using='my_db_alias')

事务和原始 SQL

当你执行了原始 SQL 之后, Django 会自动把当前事务放入黑箱。你必须确保事务正确结束。
Django 1.3 版之前,当使用原始 SQL 时必须通过 transaction.set_dirty() 手动把事务放入黑箱。
在Django的ORM中,想使用事务操作时,要先导入一个Django的内置模块

from django.db import transaction
  def index(request):
from django.db import transaction
try:
with transaction.atomic():
models.Userinfo.objects.create(username="python001",email="python001@qq.com")
models.Group.objects.create(title="python002")
except Exception as e:
return HttpResponse("出现错误....")
return HttpResponse("ok")

连接和指针

连接 和  指针 大多数执行标准  Python DB-API (除非是为了  事务处理 )。如果你不熟悉 Python DB-API ,那么要注意 cursor.execute() 中的 SQL 语句使用占位符 "%s" 比直接在 SQL 中添加参数要好。如果你使用了这个技术,那么基础数据库会根据需要为你的参数自动添加引号和转义符。这样做是符合一致性原则的,并且是一种聪明的作法。(还要注意 Django 使用 "%s" 作为占位符,而 不是 "?" 。)

在django中,执行原始sql语句的更多相关文章

  1. Django中执行原生SQL语句【新编辑】

    参考我的个人博客 这部分迁移到了个人博客中:Django中执行原生SQL语句 这里需要补充一下,还有一个extra方法: ret = models.Student.objects.all().extr ...

  2. thinkPHP框架中执行原生SQL语句的方法

    这篇文章主要介绍了thinkPHP框架中执行原生SQL语句的方法,结合实例形式分析了thinkPHP中执行原生SQL语句的相关操作技巧,并简单分析了query与execute方法的使用区别,需要的朋友 ...

  3. django系列5.4--ORM中执行原生SQL语句, Python脚本中调用django环境

    ORM执行原生sql语句 在模型查询API不够用的情况下,我们还可以使用原始的SQL语句进行查询. Django 提供两种方法使用原始SQL进行查询:一种是使用raw()方法,进行原始SQL查询并返回 ...

  4. 在django中使用原生sql语句

    raw # row方法:(掺杂着原生sql和orm来执行的操作) res = CookBook.objects.raw('select id as nid from epos_cookbook whe ...

  5. Hibernate 执行原始SQL语句

    在hibernate中有时不需要用到表的映射,需要直接执行SQL语句. 其中sessionFactory在配置文件中配置,SSH详细配置见http://blog.csdn.NET/xumengxing ...

  6. EntityFramework 4/5/6 中执行自定义SQL语句

    参考:http://www.cnblogs.com/chengxiaohui/articles/2092001.html 在EF4(.NET  4)中,我们有了全新的API:ObjectContext ...

  7. 存储过程中执行动态Sql语句

    MSSQL为我们提供了两种动态执行SQL语句的命令,分别是EXEC和sp_executesql;通常,sp_executesql则更具有优势,它提供了输入输出接口,而EXEC没有.还有一个最大的好处就 ...

  8. 怎样SQL存储过程中执行动态SQL语句

    MSSQL为我们提供了两种动态执行SQL语句的命令,分别是EXEC和sp_executesql;通常,sp_executesql则更具有优势,它提供了输入输出接口,而EXEC没有.还有一个最大的好处就 ...

  9. PlSqlDev中执行INSERT SQL语句包含&符号导致数据异常

    在PLSQL Developer中执行Insert语句时提示如下信息: 当时未注意,直接点击OK按钮继续. 导入数据后查看发现部分数据中的参数丢失了一部分,呈以下规律: . 而正常应为: . 经询问大 ...

随机推荐

  1. 论 微服务 和 Entity Framework 对 数据 的 割裂

    微服务 的 本质 是 面向对象, 微服务 是 面向对象 对 数据中心 发起的挑战, 在 微服务 架构下, “数据为中心” 的 传统架构 被 严重 割裂, 微服务 的 先天矛盾, 是 对象 和 数据 的 ...

  2. 配置中心Client端

    配置中心Client端 1.在Order工程中的Order-Server模块的pom.xml中增加 <dependency> <groupId>org.springframew ...

  3. CentOS6.5_64位系统下安装配置postfix邮件系统 启用并配置SMTP虚拟账户

    http://blog.jjonline.cn/linux/185.html http://www.cnblogs.com/apexchu/p/4271264.html 用户新增和删除 http:// ...

  4. JAVA面试-java虚拟机

    1.JVM简析:      作为一名Java使用者,掌握JVM的体系结构也是很有必要的.      说起Java,我们首先想到的是Java编程语言,然而事实上,Java是一种技术,它由四方面组成:Ja ...

  5. 各种类型的Json格式化

    using System; using System.Collections.Generic; using System.Text; using System.Data; using System.R ...

  6. GPIO实验

    一.目标:点亮led 1.看原理图:怎样点亮led 2.怎样GPF4输出0/1 a.配置功能  输出/输入/其他功能(中断或者其他) b.设置输出高电平/低电平 操作寄存器--->看芯片手册 A ...

  7. Ubuntu 14.10 下编译Hadoop2.4.0

    在http://www.aboutyun.com/thread-8130-1-1.html 这里看到到,安装过程遇到了上面说的问题,所以将此文转载过来,以备不时之需,感谢此作者. 问题导读: 1.如果 ...

  8. C++之单例类模板

    单例类模板:一个类只能有一个对象,比如超市收银系统中清点物品的仪器只有一个 设计思路: 1.构造函数,拷贝构造函数必须设计为private,防止自己生成新的对象 2.且类的指针要设计为static类型 ...

  9. Linux CentOS 下关闭防火墙

    永久关闭(重启后生效) 开启: chkconfig iptables on 关闭: chkconfig iptables off 临时关闭(重启后失效) 开启: service iptables st ...

  10. 网站优化URL需要注意的几个细节

     原文地址:http://www.douban.com/note/474016612/   一个好的URL结构无论是对搜索引擎,还是用户,都具有非常重要的作用,那么什么样的URL才是既能面向搜索引擎, ...