【问题标题】:Django regexp in field字段中的 Django 正则表达式
【发布时间】: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' 用一些表达式?

【问题讨论】:

    标签: mysql sql regex django mariadb


    【解决方案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 方法
      猜你喜欢
      • 1970-01-01
      • 2014-01-29
      • 2019-03-08
      • 2015-01-30
      • 2021-11-12
      • 2020-03-31
      • 2013-06-09
      • 1970-01-01
      • 2012-10-21
      相关资源
      最近更新 更多