我有一个案例,我已经定义了一些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/
。
答案 0 :(得分:2)
有几个javascript reverse
实现。
http://djangojs.readthedocs.org/en/latest/djangojs.html#reverse-urls
https://github.com/version2/django-js-reverse
这不是正则表达式,但您可以像在服务器中一样测试客户端代码中的URL,因此我认为它更好。
编辑:由于您需要忽略网址参数,因此您可以从django-js here的来源获得一个想法。它已经删除了可选的URL参数,因此它可能与您描述的非常相似。
代码会迭代每个模式,从每个参数subregex中删除?P
,这样您就可以用.*
替换它们。
关键是你在源代码中有可能需要执行所有正则表达式。请参阅第24-29行中的全局模式。
答案 1 :(得分: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...
我可以使用names
和args
执行某些操作。例如,我可以保留命名处理程序的字典,我可以搜索处理程序(基于names
)并使用args
调用它。
这是适合我的解决方案。将urlpatterns
转换为JavaScript模式可能并不完美(因为converter
似乎有点过于简化)但它适用于大多数简单的情况。
答案 2 :(得分: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]
答案 3 :(得分:1)
不是答案,但可能对其他人有用。
以下内容根据@Freakish的代码生成Django项目中所有完整url模式的列表,包括嵌套URLRegexResolvers
。
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))
答案 4 :(得分:0)
据我所知,您希望能够返回给定视图的正则表达式(而不是url)。
这是我的解决方案草图:
函数url返回RegexURLResolver
的实例。此类确实存储了正则表达式,因为它在__init__
(LocaleRegexProvider和in this line)上调用this line。
所以,我认为你可以
LocaleRegexProvider._regex
(或regex())的_regex。我不确定这是否有效(没有经过测试),也不是最好的解决方案,但至少你有一些关于Django存储正则表达式的链接。