12

我有一个案例,我定义了一些 Django url 模式,现在我想检索与给定模式关联的正则表达式。我想要那个,因为我想将这些正则表达式传递给客户端,这样我也可以检查客户端中的 url(我说的是浏览器端历史操作)并在匹配时触发适当的处理程序(在 JavaScript 中)。

例如,如果我有:

# urls.py
urlpatterns = patterns("",
    url(r"^$", Index.as_view(), name="index"),
    url(r"^user/", include("User.urls", namespace="User")),
)

# User/urls.py
urlpatterns = patterns("",
    url(r"^profile/(?P<slug>.*)$", GetProfile.as_view(), name="get_profile")
)

那么我需要以下功能:

>>> get_regex("User:get_profile")
'^user/profile/(?P<slug>.*)$'

(或者无论如何 Django 翻译它)。请注意,我正在使用命名空间。有任何想法吗?Django1.5。

此外,我还设法编写了一个函数,该函数返回与传递的名称关联的 urlpattern 对象,但是执行url.regex.pattern返回'^profile/(?P<slug>.*)$。所以你可以看到没有领导^user/

4

5 回答 5

2

所以我尝试了几件事,最后我想出了自己的解决方案。首先,我将 urlpatterns 转换为 JavaScript 可以理解的形式:

import re
converter = re.compile(r"\?P<.*?>")

def recursive_parse(urlpatterns, lst):
    for pattern in urlpatterns:
        obj = {
            "pattern": converter.sub("", pattern.regex.pattern)
        }
        if hasattr(pattern, "name") and pattern.name is not None:
            obj["name"] = pattern.name
        if hasattr(pattern, "namespace"):
            obj["namespace"] = pattern.namespace

        if hasattr(pattern, "url_patterns"):
            if "urls" not in obj:
                obj["urls"] = []
            recursive_parse(pattern.url_patterns, obj["urls"])

        lst.append(obj)


def generate_paths(urlpatterns):
    paths = []
    recursive_parse(urlpatterns, paths)
    return paths

然后我调用generate_paths(urlpatterns), JSON-stringify 结果并将其传递给 JavaScript(请注意,在 JavaScript 中,我必须将正则表达式作为字符串转换为RegExp对象)。在 JavaScript 中我有

var recursive_check = function(url, patterns, names, args) {
    var l = patterns.length;
    for (var i = 0; i < l; i++) {
        var pat = patterns[i],
            match = pat.pattern.exec(url);
        pat.lastIndex = 0;
        if (match) {
            names.push(pat.namespace || pat.name);
            var f = match.shift(),
                url = url.replace(f, ""),
                ml = match.length;
            for (var j = 0; j < ml; j++) {
                args.push(match[j]);
            }
            if (pat.urls) {
                recursive_check(url, pat.urls, names, args);
            }
            break;
        }
    }
};

var fire_handler = function(url) {
    var names = [], args = [];
    recursive_check(url, patterns, names, args);
    // do something...
};

现在// do something...我可以用namesand做一些事情了args。例如,我可以保留一个命名处理程序的字典,我可以搜索一个处理程序(基于names)并使用args.

这就是对我有用的解决方案。转换urlpatterns为 JavaScript 模式可能并不完美(因为converter似乎有点过于简化了),但它适用于大多数简单的情况。

于 2013-09-13T10:05:41.133 回答
2

那里有几个 javascriptreverse实现。

http://djangojs.readthedocs.org/en/latest/djangojs.html#reverse-urls

https://github.com/version2/django-js-reverse

这不是正则表达式,但您可以像在服务器中一样测试客户端代码中的 url,所以我认为它更好。

编辑:由于您需要忽略 URL 参数,您可以从 django-js 的来源获得一个想法。它已经删除了可选的 URL 参数,因此它可能与您所描述的非常相似。

代码遍历?P从每个参数子正则表达式中删除的每个模式,因此您可以将它们替换为.*.

关键是您在该源中拥有执行实现可能需要的每个正则表达式。请参阅第 24-29 行中的全局模式。

于 2013-09-06T08:37:23.090 回答
1

尝试这个:

from django.core.urlresolvers import get_resolver

resolver = get_resolver(None)
url = resolver.reversed_dict.getlist('get_profile')
if url:
    pattern = url[0][1]
于 2013-09-06T09:21:20.613 回答
1

不是答案,但可能对其他人有用。

以下URLRegexResolvers基于@Freakish 的代码生成 Django 项目中所有完整的 url 模式的列表,包括嵌套的。

import re
from django.core.urlresolvers import get_resolver

converter = re.compile(r"\?P<.*?>")

def trim_leading_caret(s):
    return s[1:] if s.startswith('^') else s

def recursive_parse(urlpatterns, lst, prefix=None):
    for pattern in urlpatterns:
        path = (prefix or '') + trim_leading_caret(converter.sub("", pattern.regex.pattern))
        if hasattr(pattern, "url_patterns"):
            recursive_parse(pattern.url_patterns, lst, path)
        else:
            lst.append('^' + path)

def generate_paths(urlpatterns):
    paths = []
    recursive_parse(urlpatterns, paths)
    return paths

generate_paths(get_resolver(None))
于 2016-10-04T11:07:11.613 回答
0

据我了解,您希望能够返回给定视图的正则表达式(而不是 url)。

这是我的解决方案草图:

函数url返回一个RegexURLResolver. 这个类确实存储了正则表达式,因为它在(在这一行这一行)上调用了 LocaleRegexProvider 。__init__

所以,我认为你可以

  1. 反向搜索视图加命名空间
  2. 从元组 urlpatterns 的元组中获取该视图的元组
  3. 返回对应于视图的元组的第一个参数LocaleRegexProvider._regex(或regex())的 _regex。

我不确定这是否有效(没有测试),也不是最好的解决方案,但至少你有一些关于 Django 存储正则表达式的链接。

于 2013-09-06T09:25:41.807 回答