Django为您提供了两种执行原始SQL查询的方法:您可以使用它 Manager.raw()
来执行原始查询并返回模型实例,或者您可以完全避免模型层并直接执行自定义SQL。
1.执行原始查询
raw()
管理方法可以用来执行返回模型实例原始的SQL查询:
Manager.
raw
(raw_query,params = None,translations = 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()
是不太够:您可能需要执行不干净映射到模型,或直接执行查询 UPDATE
,INSERT
或DELETE
查询。
在这些情况下,您始终可以直接访问数据库,完全绕模型层进行路由。
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])