Python语言Django开发框架执行自定义原生sql语句方法总结

17 篇文章 1 订阅

Python语言Django开发框架执行自定义原生sql语句方法常用的有:Model.objects.extra()、Model.objects.raw(sql)、django框架内置函数connection。

使用Model.objects.extra()

Model.objects.extra(select=None, where=None, params=None, tables=None, order_by=None, select_params=None)

参数select用法:
users = User.objects.extra(select={“is_recent”: " createdate > ‘2023-09-23’ "})
执行sql:select (createdate > ‘2023-10-23’) as is_recent, data_user.id, data_user.loginname, data_user.password, data_user.createdate fromdata_user;
ps:参数select即添加额外的查询字段,额外添加的字段is_recent是一个布尔类型,条件 " createdate > ‘2023-09-23’ " 也可以是一个 sql语句,例如:users = User.objects.extra(select= {“scorecount”: “select count(*) from data_userscore where userid = data_user.id”})。
为防止sql注入,使用参数select_params优化:
users = User.objects.extra(select={“is_recent”: “createdate > %s”}, select_params=[“2023-09-23”])

参数where用法:
users = User.objects.extra(where=[“loginname like ‘%%user%%’ or fullname like ‘%%user%%’”])
如果使用的有filter(**params),即:
users = User.objects.extra(where=[“loginname like ‘%%user%%’ or fullname like ‘%%user%%’”]).filter(id=1),
那么filter与extra()是and并列关系。
为防止sql注入,可使用参数params,类似参数select_params用法。
但是当使用like “%param%“模糊查询时,需要注意%的问题,like ‘%%user%%‘中django会将%%转义为%,然后交由mysql运行,如果同时使用参数select_params,以下写法不正确:
users = User.objects.extra(where=[“loginname like ‘%%%s%%’ or fullname like ‘%%%s%%’”], params=[“user”, “user”])
需要使用以下写法:
users = User.objects.extra(where=["loginname like concat(’%%’, %s, ‘%%’) or fullname like concat(‘%%’, %s, ‘%%’)”], params=[“user”, “user”])
ps:concat是mysql内置函数,链接字符串
或者
users = User.objects.extra(where=[“loginname like %s or fullname like %s”], params=[”%“+“user”+”%“, “%”+“user”+”%"])

参数tables用法:
movies = Movie.objects.extra(tables=[“movietype”])
执行sql:select movie.id from movie, movietype,即额外查询其他表,这里暂不做举例,处理的业务相对复杂。

参数order_by用法:
users = User.objects.extra(order_by=[“-id”, “createdate”])
执行sql:select data_user.id, data_user.loginname, data_user.password, data_user.createdate fromdata_user order by id desc, createdate asc;
当需要使用特定排序时,例如:id按照1,3,2排序,sql语句如下:
select user.id from user order by field(id, 1, 3, 2);
这时就不能够使用order_by参数,最好使用以下执行自定义原生sql语句方法。

使用Model.objects.raw(sql)

sql = " select user.id from user "
users = User.objects.raw(sql),返回RawQuerySet数据类型,集合中的数据是模型类对象,RawQuerySet继承QuerySet,但是此方法有一些限制:
1、查询结果必须要有模型类主键id;
2、查询结果不能直接转字典类型,需要手动遍历转化,即不能够使用values()方法,但是QuerySet可以使用;
3、如果要分页,是先查询完再分页,即如果一次查询的数据很多,将这些数据查询完后再进行分页,分页是以list的形式分页,查询效率很低,但是QuerySet分页是执行的最终分页的sql,有数量限制。

django框架内置函数connection

使用django框架提供的connection对象实现数据库查询:
from django.db import connection
with connection.cursor() as cursor:
cursor.execute(sql, params) 执行sql语句,返回的数据中,字段和数据是分开的,没有一一对应
封装,将查询结果与数据库字段映射:

  # 查询所有数据,参数:params即查询参数
  from django.db import connection
  def query(sql, params=None):
      # 定义返回的结果
      query_data = list()
      # 查询,使用django框架提供的connection对象实现数据库查询
      with connection.cursor() as cursor:
          # 执行sql语句,返回的数据中,字段和数据是分开的,没有一一对应
          cursor.execute(sql, params)
          # 获取查询结果的字段名
          # description属性得到由字段和其他值组成的元组,格式:((字段1,...),(字段2,...)...)
          query_field_names = [k[0] for k in cursor.description]
          # 获取所有数据值,格式[(字段1的值,字段2的值....),(字段1的值,字段2的值....)],是一个由元组组成的列表
          query_field_values = cursor.fetchall()
          # 将字段名和字段值一一对应并转dict格式
          for query_field_value in query_field_values:
              result = dict(zip(query_field_names, query_field_value))
              query_data.append(result)
      return query_data
  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

linge511873822

亲的鼓励是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值