Django中的简单查询

时间:2018-09-16 16:47:32

标签: python sql django

我正在尝试像这样进行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中则无法运行。

1 个答案:

答案 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对象之后,因此idusername等列本身不多,则通过删除.values_list(..)可以得到User个对象,而不是列表的QuerySet