Django 高级 LIKE 过滤

Django advanced LIKE filtering

所以我试图找到一种在 Django 中使用 LIKE 语句执行高级过滤器的好方法。

假设我在名为 elements 的 table 中有以下记录:

id = 1, name = 'group[1].car[8]'
id = 2, name = 'group[1].car[9]'
id = 3, name = 'group[1].truck[1]'
id = 4, name = 'group[1].car[10]'
id = 4, name = 'group[1].carVendor[1]'

我想 select 所有看起来像 group[x].car[y] 的元素。

要在 SQL 中查询,我会这样做:

SELECT * FROM elements WHERE name LIKE 'group[%].car[%]'

现在,通过阅读 Django 文档 here,我看到唯一预构建的 LIKE 语句如下:

  1. 包含:name LIKE '%something%'
  2. 开头为:name LIKE 'something%'
  3. 结尾:name LIKE '%something'

所以我需要的那个不见了:

  1. 普通喜欢:name LIKE 'group[%].car[%]'

我也在使用 Django Rest Framework 编写我的 API 端点,并且在这里我们找到了使用的可能性:

  1. 包含:name__contains = something
  2. 开头为:name__startswith = something
  3. 结尾:name__endswith = something

所以这里也是,我需要的那个不见了:

  1. 平淡如:name__like 'group[%].car[%]'

当然我知道我可以使用 raw() 方法通过 Django 编写原始 sql 查询,但如果没有更好的解决方案出现,我想使用此选项,因为:

  1. 我需要确保我的定制是安全的
  2. 我需要将自定义扩展到 DRF

任何人都可以想出一种方法来帮助我解决这个问题,同时使用 Django 和 Django Rest Framework 吗?

您可以使用 regular expression (regex) [wiki] for this, with the __iregex lookup [Django-doc]:

Elements.objects.filter(name<b>__iregex=r'^group\[.*\].car\[.*\]$'</b>)

如果在方括号之间,只允许数字,我们可以通过以下方式使其更具体:

# only digits between the square brackets
Elements.objects.filter(name__iregex=r'^group\[<b>\d*</b>\].car\[<b>\d*</b>\]$')

因为有些规范有点"complex",最好先测试你的正则表达式,例如regex101你可以看看names 会匹配,which 不会。