django 使用原生sql

Django中查询筛选数据时,大多数是使用封装好的orm,其中有一些较为复杂的sql语句很难使用orm实现,因此在此引入Django中原生sql的使用方法

在Django中使用原生Sql主要有以下三种方法:
一:extra:结果集修改器,一种提供额外查询参数的机制
二:raw:执行原始sql并返回模型实例
三:直接执行自定义Sql

下面列举django文档中的例子

from django.db import models

class Book(models.Model):
    name = models.CharField('书名')
    price = models.IntegerField('价钱')
    publish = models.CharField('出版社')
    create_time = models.DateTimeField('上线日期'

1.extra:结果集修改器,是吗一种提供额外查询参数的机制

books= Book.objects.filter(publish='清华出版社').extra(where=['price>50'])

此方法适合用于orm难以实现的某个筛选条件,将这个条件单独选出,使用原生sql进行筛选。此方法也依然主要依靠与orm
谨慎使用,防止sql注入问题

2.raw:执行原始sql并返回模型实例

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

books = Book.objects.raw('select * from book where publish="清华出版社"')

或者,您可以使用translations参数to 将查询中的字段映射到模型字段 raw()。这是一个字典,将查询中字段的名称映射到模型上字段的名称。例如,上面的查询也可以写成:

name_map = {'user_name': 'name', 'book_price': 'price', 'pls': 'publish', 'time': 'create_time'}
Book.objects.raw('SELECT * FROM book', translations=name_map)

此方法在执行完原生sql后,返回一个orm的实例

3.直接执行自定义Sql

from django.db import connection                                              # django封装好的方法
cursor=connection.cursor()                                                    # 建立游标                

cursor.execute("insert into book(name) values('小王子')")                        #插入操作

cursor.execute('update book set name='梦里花落知多少' where name='撒哈拉的故事'') #更新操作

cursor.execute('delete from book where name='小王子'')                           #删除操作

cursor.execute('select * from book')                                          #查询操作
raw = cursor.fetchone()                                                       #读取一条
raw_list = cursor.fetchall()                                                  #读取所有,返回list
cursor.close()  #关闭游标

另一种更好的方法,采用django文档种的语句

rom django.db import connection

def my_custom_sql(self):
    with connection.cursor() as cursor:                        # with语句相当与cursor= connection.cursor() 和 cursor.close(),简化了语句
        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.connections获取特定数据库的连接(和游标)。django.db.connections是一个类似字典的对象,允许您使用其别名检索特定连接:

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

此方法是真正的完全抛弃orm,直接使用原生sql,django中也有封装好的connection方法使用,只要sql语句使用流畅,此方法也比较方便。

默认情况下,Python DB API将返回没有字段名称的结果,这意味着您最终会得到一个list值,而不是一个dict。在较小的性能和内存成本下,您可以使用以下内容返回结果dict:

def dictfetchall(cursor):
    "Return all rows from a cursor as a dict"
    columns = [col[0] for col in cursor.description]
    return [
        dict(zip(columns, row))
        for row in cursor.fetchall()
    ]

 # 结果例子
 # [{'parent_id': None, 'id': 54360982}, {'parent_id': None, 'id': 54360880}]

另一种选择是使用collections.namedtuple()Python标准库。A namedtuple是一个类似元组的对象,其字段可通过属性查找访问; 它也是可索引和可​​迭代的。结果是不可变的,可以通过字段名称或索引访问,这可能很有用:

from collections import namedtuple

def namedtuplefetchall(cursor):
    "Return all rows from a cursor as a namedtuple"
    desc = cursor.description
    nt_result = namedtuple('Result', [col[0] for col in desc])
    return [nt_result(*row) for row in cursor.fetchall()]

# 结果例子
# [Result(id=54360982, parent_id=None), Result(id=54360880, parent_id=None)]

你可能感兴趣的:(Django)