我正在尝试像这样进行RAW查询:
User.objects.raw("SELECT username FROM app_user WHERE id != {0} AND LOWER(username) LIKE LOWER('%{1}%')".format('1','john'))
我收到此错误:
django.db.utils.ProgrammingError: not enough arguments for format string
该查询在SQLite中可以完美运行,但在MySQL中则无法运行。
答案 0 :(得分:2)
执行格式化后,Django将获得以下查询:
SELECT username FROM app_user WHERE id != 1 AND LOWER(username) LIKE LOWER('%john%')
如您所见,该字符串包含%j
和%)
。这是另一种在Python中格式化字符串格式的方法的一部分,Django将使用该方法以正确的方式 inject 来参数。因此,它寻找额外的参数。但找不到任何东西。
但是无论发生什么情况,这都不是一个好主意,因为此类查询容易受到SQL注入的攻击。如果以后将'John'
替换为'); DROP TABLE app_user --
(或类似的名称),那么有人可以删除整个表。
如果要执行这样的查询,它应该类似于:
User.objects.raw(
"SELECT username FROM app_user WHERE id != %s AND LOWER(username) LIKE LOWER('%%%s%%')",
['1','john']
)
或更妙的是:使用Django ORM:
User.objects.exclude(id=1).filter(
username__icontains='john'
).values_list('username', flat=True)
或者我们可以将完整的查询编码为:
User.objects.exclude(id=request.user.pk).annotate(
flname=Concat('first_name', Value(' '), 'last_name')
).filter(
Q(username__icontains=q) | Q(flname__icontains=q)
).values_list('id', 'username', 'first_name', 'last_name')
如果您是在User
对象之后,因此id
,username
等列本身不多,则通过删除.values_list(..)
可以得到User
个对象,而不是列表的QuerySet
。