字段中的 Django 正则表达式
Posted
技术标签:
【中文标题】字段中的 Django 正则表达式【英文标题】:Django regexp in field 【发布时间】:2016-06-01 02:57:02 【问题描述】:我有模特:
class M(Model):
re = CharacterField(max_length=50, blank=true)
例如在表中我有:
table m
----------------
| id | re |
----------------
| 1 | \d+ |
| 2 | \:abc |
----------------
我想通过存储在re
字段中的正则表达式找到与我的输入字符串 (inp
) 匹配的对象,请参见示例:
inp = ":abc"
for m in M.objects.all():
if re.match(m.re, inp)
print(" matched".format(m.id)) # 2 matched
但是可以在数据库服务器上执行match
吗?那么将.all()
替换为'.filter' 用一些表达式?
【问题讨论】:
【参考方案1】:for m in M.objects.filter().extra(where=["'' RLIKE `m`.`re`".format(inp)])
print(" matched".format(m.id))
【讨论】:
【参考方案2】:首先,\d
不由 mysql 处理。请改用[0-9]
或[[:digit:]]
。
其次,要在 SQL 中执行正则表达式,请构建您的应用程序
'[0-9]+|:abc'
然后将其构建到查询中。
但你可能想锚定正则表达式:
'^([0-9]+|:abc)$'
【讨论】:
感谢\d
的通知,我使用 MariaDB 服务器,它应该支持 PCRE 正则表达式。我的任务是在m
表中找到与某个输入字符串匹配的re
中的哪一行,系统管理员可以输入很多行,并且它们可以有不同的表达式 - 2 行是简化问题的非常简化的示例,没有实用价值,只有技术。【参考方案3】:
对于正则表达式匹配,您需要在filter
调用中的字段名之后使用__iregex
:
M.objects.filter(re__iregex=inp)
查看official documentation以获取更多信息
编辑
如果您想要反向操作(检查保存在数据库中的任何正则表达式是否与您的值匹配)您不能使用简单的filter
,但您可以定义您的自定义Manager
class CurrentManager(models.Manager):
def match(self, value):
objects = super(CurrentManager, self).get_query_set().all()
#here your code
objects = [o for o in objects if re.match(o, value)]
return objects
class M(Model):
re = CharacterField(max_length=50, blank=true)
objects = RegexManager()
#usage
matched = M.objects.match('123')
也看看这个question。
【讨论】:
iregex
正向工作 - 当表中的列与某些正则表达式匹配时,我需要反向操作 - 某些值与列中的正则表达式匹配。我试过M.objects.filter(re__iregex="123").first()
,它返回None
,但应该返回1
,因为123
在\d+
下匹配
谢谢,这是一个有趣且内容丰富的解决方案,一个问题:它会首先从 db 中选择所有内容,然后在 python 中找到匹配的对象吗?我的目标是在数据库服务器上执行正则表达式匹配(如果表中有很多行,我认为从数据库服务器获取所有原始数据效率不高)。好像django没有这样的过滤器所以我需要在where
子句中应用一些额外的东西,比如'WHERE REGEXP m.re'.format(inp)
,我稍后会尝试。
是的——它会按照你说的方式做事(首先全选然后在 python 级别过滤)——效率取决于行数。如果你想在 DB 上执行你自己的选择,你可以使用extra 方法以上是关于字段中的 Django 正则表达式的主要内容,如果未能解决你的问题,请参考以下文章