我可以使用 glob 模式查询数据库吗?

Can I query the DB using a glob pattern?

我在尝试使用 glob 模式查询数据库时遇到问题。

我想也许 glob 可以翻译成正则表达式,我知道 I can query db using regex. I was going to to that translation myself, but I found that python has fnmatch 可以做到这一点,明确的函数 translate

fnmatch.translate(pattern)

Return the shell-style pattern converted to a regular expression for using with re.match().

所以我尝试将两者结合起来但是...

>>> from vte.models import VTE
>>> import fnmatch
>>> regex = fnmatch.translate('19*')
>>> regex
'19.*\Z(?ms)'
>>> VTE.objects.filter(ipaddr__regex=regex)
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/var/www/vtfx/env/local/lib/python2.7/site-packages/django/db/models/query.py", line 234, in __repr__
    data = list(self[:REPR_OUTPUT_SIZE + 1])
  File "/var/www/vtfx/env/local/lib/python2.7/site-packages/django/db/models/query.py", line 258, in __iter__
    self._fetch_all()
  File "/var/www/vtfx/env/local/lib/python2.7/site-packages/django/db/models/query.py", line 1074, in _fetch_all
    self._result_cache = list(self.iterator())
  File "/var/www/vtfx/env/local/lib/python2.7/site-packages/django/db/models/query.py", line 52, in __iter__
    results = compiler.execute_sql()
  File "/var/www/vtfx/env/local/lib/python2.7/site-packages/django/db/models/sql/compiler.py", line 848, in execute_sql
    cursor.execute(sql, params)
  File "/var/www/vtfx/env/local/lib/python2.7/site-packages/django/db/backends/utils.py", line 79, in execute
    return super(CursorDebugWrapper, self).execute(sql, params)
  File "/var/www/vtfx/env/local/lib/python2.7/site-packages/django/db/backends/utils.py", line 64, in execute
    return self.cursor.execute(sql, params)
  File "/var/www/vtfx/env/local/lib/python2.7/site-packages/django/db/utils.py", line 95, in __exit__
    six.reraise(dj_exc_type, dj_exc_value, traceback)
  File "/var/www/vtfx/env/local/lib/python2.7/site-packages/django/db/backends/utils.py", line 64, in execute
    return self.cursor.execute(sql, params)
DataError: invalid regular expression: quantifier operand invalid

我不明白错误信息。

根据 django 的文档,它应该在 postgresql(顺便说一句,我正在使用的数据库)中翻译成这样的东西

SELECT ... WHERE ipaddr ~ '19.*\Z(?ms)';

Here it is the ~ operator documentation.

所以我尝试稍微更改 translate() 返回的正则表达式,并且在删除 ? 字符时不会抛出错误。

然后我想,如果没有这最后一部分,glob->regex 翻译可能工作正常 \Z(?ms) 但我不确定,我可能遗漏了一些东西。

回顾:

所以新代码应该是这样的

>>> VTE.objects.filter(ipaddr__regex=regex.replace('\Z(?ms)', ''))
[<VTE: 192.168.56.100>]

我在做 .replace('\Z(?ms)', '') 时错过了什么?为什么这是必要的?这是一个好的解决方案吗?

根据对我的问题的评论,我最终做了以下事情

import fnmatch
globex = ......
regex = '^{}'.format(fnmatch.translate(globex).replace('\Z(?ms)', '$'))
VTE.objects.filter(ipaddr__regex=regex)

这似乎与 postgresql 和 javascript 正则表达式实现兼容。