当前位置 博文首页 > 手把手教你用Django执行原生SQL的方法

    手把手教你用Django执行原生SQL的方法

    作者:Python进阶者 时间:2021-07-26 17:49

    前言

    Hey,各位小伙伴,这次怎么来玩一下,如何使用Django执行原生SQL。

    我们都知道,Python在web界的扛把子——Django,可谓是集大成为统一,各种各样的插件、forms组件、model模型、Admin后台等等,后面我会专门出文章娓娓道来,反正就是一个字,NB。

    本次就来学一下,如何在Django执行原生语句。

    起因

    在使用Django时,一般情况下,我们使用Django自带的model查询是没有问题的,基本能满足80%的问题

    但是,但是,那20%就不要了吗???肯定不行哎,小孩才做选择

    在Django执行原生SQL有以下三种方式

    • extra
    • raw
    • django connection

    一般情况下,就以上三种方式

    表结构

    文件:django_project/app01/models

    class Book(models.Model): 
      title = models.CharField(verbose_name="书名", max_length=32) 
      describe = models.TextField(verbose_name="描述") 
      author = models.CharField(verbose_name="作者", max_length=32) 
      publisher = models.CharField(verbose_name="出版社", max_length=32) 
      publisher_date = models.DateField(verbose_name="publisher") 

    就是一个很简单的图书表

    通过admin录入一些数据测试使用

    extra方式

    强烈建议,不用学,没毛用

    raw方式

    这个相比较extra,还是比较有用的,

    语法如下

    models.表名.objecs.raw(sql) 
    models.表名.objecs.raw(sql,[参数1,参数2]) 

    注:如果没有参数,就只写sql语句,如果由参数,后面需要用列表,如图所示

    举例

    返回的仍然一个个的Book对象

    真正的原生sql方式

    上述的,其实还是和django的model有些绑定。但是我就是说,我就是想要原生sql,不要跟任何绑定。

    这里说一下,千万不要在django使用pymysql执行原生sql,会发生一些奇怪的问题。一定要导入from django.db import connection执行sql。代码如下:

    from django.db import connection 
    def book_list(request): 
      # 真正的原生sql, 
      cursor = connection.cursor() 
      print(type(cursor)) 
      cursor.execute("select * from app01_book where id=%s", [1, ]) 
      raw = cursor.fetchall() 
      print(raw) 

    返回内容如下图所示:

    可以看到,返回的是列表里面套一个个的数组。我就在想,有没有什么办法能将查询出来的sql,直接返回成字典呢?答案是当然可以!

    执行原生sql并且返回成dict

    我将执行原生sql并且直接返回成字典的方式封装成了两个函数

    一个是查询多个,代码如下所示:

    def query_all_dict(sql, params=None): 
      ''' 
      查询所有结果返回字典类型数据 
      :param sql: 
      :param params: 
      :return: 
      ''' 
      with connection.cursor() as cursor: 
        if params: 
          cursor.execute(sql, params=params) 
        else: 
          cursor.execute(sql) 
        col_names = [desc[0] for desc in cursor.description] 
        row = cursor.fetchall() 
        rowList = [] 
        for list in row: 
          tMap = dict(zip(col_names, list)) 
          rowList.append(tMap) 
        return rowList 

    一个是查询一个,代码如下所示:

    def query_one_dict(sql, params=None): 
      """ 
      查询一个结果返回字典类型数据 
      :param sql: 
      :param params: 
      :return: 
      """ 
      with connection.cursor() as cursor: 
        if params: 
          cursor.execute(sql, params=params) 
        else: 
          cursor.execute(sql) 
        col_names = [desc[0] for desc in cursor.description] 
        row = cursor.fetchone() 
        tMap = dict(zip(col_names, row)) 
        return tMap 

    用法如下,直接在视图中调用函数

    返回结果如下,直接是列表套字典格式

    那查询带条件的怎么办哪,其实和pymysql一个样

    返回结果

    但是有个问题,上面的查询,我们明明知道,让只会返回一个值,但是还是返回的是列表套字典格式,似乎不太对呐?

    其实上述我写的是两个办法,如果确定就查询一个值,使用query_one_dict方法。

    上述总结

    django中执行原生sql有3种方式,extra,raw,from django.db import connection

    其中extra基本没用,raw凑合,但是和models有绑定,connection最灵活,但是默认返回的是[tuple,tuple,tuple,]格式

    经过改良,封装出两个方法,query_all_dict,query_one_dict,一个是查询多个,一个是查询单个,并且返回成[dict,dict,dict,]

    建议

    只使用query_all_dict,query_one_dict

    项目代码

    django_exec_sql.zip 

    需要本文完整代码的小伙伴,可以在本公众号后台回复关键字:原生SQL,进行获取。

    总结

    上述以入门的方式解决了安排了以下如何通过django执行原生sql。

    用微笑告诉别人,今天的我比昨天强,今后也一样。

    jsjbwy
    下一篇:没有了