Django原始SQL查询需要注意的问题

Django为您提供了两种执行原始SQL查询的方法:您可以使用它 Manager.raw()执行原始查询并返回模型实例,或者您可以完全避免模型层并直接执行自定义SQL

 

1.执行原始查询

raw()管理方法可以用来执行返回模型实例原始的SQL查询:

Manager.rawraw_queryparams = Nonetranslations = None

此方法接受原始SQL查询,执行它并返回 django.db.models.query.RawQuerySet实例。这个RawQuerySet实例可以像普通一样迭代, QuerySet以提供对象实例。

举例

class ScenceFlow(models.Model):
    """
    地区实时客流量数据
    """
    pid = models.SmallIntegerField(verbose_name="标识")
    ddate = models.IntegerField(verbose_name="日期,格式为yyyymmdd")
    ttime = models.TimeField(verbose_name="时间,格式为HH:MM:SS")
    num = models.IntegerField(verbose_name="总人数")

    def __str__(self):
        return "标识:{0},日期:{1},时间:{2},数量:{3}".format(self.pid, self.ddate, self.ttime, self.num)

    class Meta:
        db_table = "scenceflow"
        unique_together = [['pid', 'ddate', 'ttime', 'num']]

然后,您可以执行自定义SQL,如下所示:

下面有两种写法,你觉得哪种是正确的?

    result = ScenceFlow.objects.raw('select id,ttime,num from digitalsmart.scenceflow where pid=%s and ddate=%s',

                                    params=[2, 20190722])
    result = ScenceFlow.objects.raw('select id,ttime,num from digitalsmart.scenceflow where pid=%d and ddate=%d',

                                    params=[2, 20190722])

咋一看觉得第二种写法是正确的,因为数据类型对应,理论上应该是正确的

咋们先看看第二种的执行结果:

发现类型错误,怎么回事???我们输入的是数字类型的呀,没错啊,怎么回事字符串类型的呢

其实格式化字符串是没错的,但是这里格式字符串实际上不是普通的Python格式字符串,您必须始终使用%s所有字段,它只是一个自定义字符串插值实现。它类似于Python,但不是普通的Python。这样做是为了逃避值以防止SQL注入。

 

2.直接执行自定义

 

有时甚至Manager.raw()是不太够:您可能需要执行不干净映射到模型,或直接执行查询 UPDATEINSERTDELETE查询。

在这些情况下,您始终可以直接访问数据库,完全绕模型层进行路由。

 

django.db.connection表示默认的数据库连接。要使用数据库连接,请调用connection.cursor()以获取游标对象。然后,调用执行SQL和或返回结果行。

    with connection.cursor() as cursor:
        cursor.execute("select ttime,num from digitalsmart.scenceflow "
                       "where pid= %s and ddate=%s ", [pid, date_begin])
        row = cursor.fetchall()

注意:要防止SQL注入,您不得%s 在SQL字符串中的占位符周围包含引号;如果要在查询中包含文字百分号,则在传递参数时必须将它们加倍。

cursor.execute("SELECT foo FROM bar WHERE baz = '30%'")
cursor.execute("SELECT foo FROM bar WHERE baz = '30%%' AND id = %s", [self.id])

 

 

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值