django执行原生SQL查询的实现

目录
  • 执行原生 sql 查询
  • 2、直接执行自定义 sql

执行原生 sql 查询

django 允许你用两种方式执行原生 sql 查询:

  • 你可以使用 manager.raw() 来 执行原生查询并返回模型实例。
  • 或者完全不用模型层 直接执行自定义 sql。

1、执行原生查询

管理器方法 raw() 能用于执行原生 sql 查询,就会返回模型实例:

manager.raw(raw_query, params=none, translations=none)

该方法接受一个原生 sql 查询语句,执行它,并返回一个 django.db.models.query.rawqueryset 实例。这个 rawqueryset 能像普通的 queryset 一样被迭代获取对象实例。

1.1 普通查询

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 app_person'): # django默认的表名是app名加类名
    print(p)
​# 没有查询到就报错

1.2 将查询字段映射为模型字段

raw() 字段将查询语句中的字段映射至模型中的字段。
查询语句中的字段排序并不重要。换而言之,以下两种查询是一致的:

person.objects.raw('select id, first_name, last_name, birth_date from app_person')

person.objects.raw('select last_name, birth_date, first_name, id from app_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 app_person''')

只要名字对上了,模型实例就会被正确创建。

或者,你可以用 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)

1.3 索引查询

raw() 支持索引,所以,若你只需要第一个结果就这样写:

>>> first_person = person.objects.raw('select * from app_person')[0]

1.4 将参数传给 raw()

如果你需要执行参数化的查询,可以使用 raw() 的 params 参数:

>>> lname = 'doe'
>>> person.objects.raw('select * from myapp_person where last_name = %s', [lname])

params 是一个参数字典。你将用一个列表替换查询字符串中 %s 占位符,或用字典替换 %(key)s 占位符(其中, key 理所应当由字典 key 替换),不论你使用哪个数据库引擎。这些占位符会被 params 参数的值替换。
!!!必须以列表形式传入参数,格式一定是这样写,不能写成字符串

2、直接执行自定义 sql

绕过模型层。

对象 django.db.connection 代表默认数据库连接。要使用这个数据库连接,调用 connection.cursor() 来获取一个指针对象。然后,调用 cursor.execute(sql, [params]) 来执行该 sql 和 cursor.fetchone(),或 cursor.fetchall() 获取结果数据。

from django.db import connection
​
def my_sql(self):
    with connection.cursor() as 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

要避免 sql 注入,你绝对不能在 sql 字符串中用引号包裹 %s 占位符。
注意,若要在查询中包含文本的百分号,你需要在传入参数使用两个百分号:

cursor.execute("select foo from bar where baz = '30%%' and id = %s", [self.id])

2.1 指定连接数据库

用 django.db.connections 获取指定数据库的连接(和指针)。 django.db.connections 是一个类字典对象,它允许你通过连接别名获取指定连接:

from django.db import connections
with connections['my_db_alias'].cursor() as cursor:

 到此这篇关于django执行原生sql查询的实现的文章就介绍到这了,更多相关django执行原生sql查询内容请搜索www.887551.com以前的文章或继续浏览下面的相关文章希望大家以后多多支持www.887551.com!

(0)
上一篇 2022年3月21日
下一篇 2022年3月21日

相关推荐