I have a case where I have defined some Django url patterns and now I want to retrieve the regular expression associated with a given pattern. I want that because I want to pass these regular expressions to the client so I can check urls in client as well ( I'm talking about browser side history manipulation ) and fire appropriate handlers ( in JavaScript ) when there is a match.
我已经定义了一些Django url模式,现在我想检索与给定模式关联的正则表达式。我想这样做是因为我想把这些正则表达式传递给客户端,这样我也可以检查客户端中的url(我说的是浏览器端历史处理),并在匹配时触发适当的处理程序(用JavaScript)。
For example if I have:
例如,如果我有:
# 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")
)
then I need the following function:
那么我需要以下功能:
>>> get_regex("User:get_profile")
'^user/profile/(?P<slug>.*)$'
( or however Django translates it ). Note that I'm using namespaces. Any ideas? Django1.5.
(或者用Django的说法)。注意,我正在使用名称空间。什么好主意吗?Django1.5。
Also I've managed to write a function that returns the urlpattern object associated with a passed name, however doing url.regex.pattern
returns '^profile/(?P<slug>.*)$
. So as you can see there is no leading ^user/
.
此外,我还编写了一个函数,该函数返回与传递的名称关联的urlpattern对象,但是要执行url.regex。模式回报' ^概要/(? P <蛞蝓> 。*)美元。你们可以看到没有领先用户/ ^。
5 个解决方案
#1
2
There are several javascript reverse
implementations out there.
有几个javascript反向实现。
http://djangojs.readthedocs.org/en/latest/djangojs.html#reverse-urls
http://djangojs.readthedocs.org/en/latest/djangojs.html reverse-urls
https://github.com/version2/django-js-reverse
https://github.com/version2/django-js-reverse
It's not the regex, but you could test the urls in your client code just like you do in the server, so it's even better in my opinion.
它不是regex,但是您可以在客户机代码中测试url,就像在服务器中测试一样,因此在我看来,它甚至更好。
EDIT: Since you need to ignore URL arguments, you could get an idea from the source of django-js here. It already removes optional URL arguments, so it's probably very similar to what you describe.
编辑:因为您需要忽略URL参数,所以您可以从这里的django-js源代码中获得一个想法。它已经删除了可选的URL参数,因此它可能与您所描述的非常相似。
The code iterates over every pattern removing the ?P
from each argument subregex so you could just replace them with .*
.
代码遍历每个模式,从每个参数subregex中删除?P,以便您可以用.*替换它们。
The point is you have in that source every regex you could possibly need to do your implementation. See the global patterns in lines 24-29.
关键是,在该源代码中,您可能需要执行实现的每个regex。请参见第24-29行中的全局模式。
#2
2
So I've tried few things and finally I came up with my own solution. First I convert urlpatterns into a form which JavaScript understands:
所以我尝试了一些东西,最后我找到了我自己的解决方案。首先,我将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
Then I call generate_paths(urlpatterns)
, JSON-stringify the result and pass it to JavaScript (note that in JavaScript I have to convert regular expressions as strings to RegExp
objects). In JavaScript I have
然后我调用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...
};
Now in // do something...
I can do something with names
and args
. For example I can keep a dictionary of named handlers, I can search for a handler (based on names
) and call it with args
.
现在做点什么……我可以用名字和arg做点什么。例如,我可以保存一个命名处理程序的字典,我可以搜索一个处理程序(基于名称)并使用args调用它。
That's the solution that works for me. Converting urlpatterns
to JavaScript patterns might not be perfect (since converter
seems to be a bit too simplified) but it works in most simple cases.
这对我来说是可行的。将urlpatterns转换为JavaScript模式可能并不完美(因为转换器似乎过于简化),但在大多数简单的情况下它都能工作。
#3
1
Try this:
试试这个:
from django.core.urlresolvers import get_resolver
resolver = get_resolver(None)
url = resolver.reversed_dict.getlist('get_profile')
if url:
pattern = url[0][1]
#4
0
As far as I understood, you want to be able to return the regex expression (and not the url) of a given view.
据我所知,您希望能够返回给定视图的regex表达式(而不是url)。
This is my sketch of solution:
这是我的解决方案:
The function url returns an instance of RegexURLResolver
. This class does store the regex, because it calls LocaleRegexProvider on __init__
(in this line and this line).
函数url返回RegexURLResolver的实例。这个类确实存储了regex,因为它在__init__(在这一行和这一行)上调用LocaleRegexProvider。
So, I think that you can
所以,我认为你可以
- reverse search the view plus namespace
- 反向搜索视图+名称空间
- get the tuple of that view from the tuple of tuples urlpatterns
- 从tuples urlpatterns的tuple获取该视图的tuple
- return _regex of the first argument,
LocaleRegexProvider._regex
(or regex()), of the tuple respective to the view. - 返回第一个参数LocaleRegexProvider的_regex。与视图相关的元组的_regex(或regex())。
I'm not sure this works (didn't tested), neither that it is the best solution, but at least you have some links on where Django stores the regex.
我不确定这是否有效(没有经过测试),也不认为这是最好的解决方案,但至少您有一些关于Django在哪里存储regex的链接。
#5
0
Not an answer but might be useful to someone else looking at this.
不是一个答案,但可能对其他人有用。
The following generates a list of all, complete url patterns in the Django project, including for nested URLRegexResolvers
, based on @Freakish's code.
下面的代码生成了Django项目中所有完整的url模式的列表,包括基于@Freakish代码的嵌套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))
#1
2
There are several javascript reverse
implementations out there.
有几个javascript反向实现。
http://djangojs.readthedocs.org/en/latest/djangojs.html#reverse-urls
http://djangojs.readthedocs.org/en/latest/djangojs.html reverse-urls
https://github.com/version2/django-js-reverse
https://github.com/version2/django-js-reverse
It's not the regex, but you could test the urls in your client code just like you do in the server, so it's even better in my opinion.
它不是regex,但是您可以在客户机代码中测试url,就像在服务器中测试一样,因此在我看来,它甚至更好。
EDIT: Since you need to ignore URL arguments, you could get an idea from the source of django-js here. It already removes optional URL arguments, so it's probably very similar to what you describe.
编辑:因为您需要忽略URL参数,所以您可以从这里的django-js源代码中获得一个想法。它已经删除了可选的URL参数,因此它可能与您所描述的非常相似。
The code iterates over every pattern removing the ?P
from each argument subregex so you could just replace them with .*
.
代码遍历每个模式,从每个参数subregex中删除?P,以便您可以用.*替换它们。
The point is you have in that source every regex you could possibly need to do your implementation. See the global patterns in lines 24-29.
关键是,在该源代码中,您可能需要执行实现的每个regex。请参见第24-29行中的全局模式。
#2
2
So I've tried few things and finally I came up with my own solution. First I convert urlpatterns into a form which JavaScript understands:
所以我尝试了一些东西,最后我找到了我自己的解决方案。首先,我将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
Then I call generate_paths(urlpatterns)
, JSON-stringify the result and pass it to JavaScript (note that in JavaScript I have to convert regular expressions as strings to RegExp
objects). In JavaScript I have
然后我调用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...
};
Now in // do something...
I can do something with names
and args
. For example I can keep a dictionary of named handlers, I can search for a handler (based on names
) and call it with args
.
现在做点什么……我可以用名字和arg做点什么。例如,我可以保存一个命名处理程序的字典,我可以搜索一个处理程序(基于名称)并使用args调用它。
That's the solution that works for me. Converting urlpatterns
to JavaScript patterns might not be perfect (since converter
seems to be a bit too simplified) but it works in most simple cases.
这对我来说是可行的。将urlpatterns转换为JavaScript模式可能并不完美(因为转换器似乎过于简化),但在大多数简单的情况下它都能工作。
#3
1
Try this:
试试这个:
from django.core.urlresolvers import get_resolver
resolver = get_resolver(None)
url = resolver.reversed_dict.getlist('get_profile')
if url:
pattern = url[0][1]
#4
0
As far as I understood, you want to be able to return the regex expression (and not the url) of a given view.
据我所知,您希望能够返回给定视图的regex表达式(而不是url)。
This is my sketch of solution:
这是我的解决方案:
The function url returns an instance of RegexURLResolver
. This class does store the regex, because it calls LocaleRegexProvider on __init__
(in this line and this line).
函数url返回RegexURLResolver的实例。这个类确实存储了regex,因为它在__init__(在这一行和这一行)上调用LocaleRegexProvider。
So, I think that you can
所以,我认为你可以
- reverse search the view plus namespace
- 反向搜索视图+名称空间
- get the tuple of that view from the tuple of tuples urlpatterns
- 从tuples urlpatterns的tuple获取该视图的tuple
- return _regex of the first argument,
LocaleRegexProvider._regex
(or regex()), of the tuple respective to the view. - 返回第一个参数LocaleRegexProvider的_regex。与视图相关的元组的_regex(或regex())。
I'm not sure this works (didn't tested), neither that it is the best solution, but at least you have some links on where Django stores the regex.
我不确定这是否有效(没有经过测试),也不认为这是最好的解决方案,但至少您有一些关于Django在哪里存储regex的链接。
#5
0
Not an answer but might be useful to someone else looking at this.
不是一个答案,但可能对其他人有用。
The following generates a list of all, complete url patterns in the Django project, including for nested URLRegexResolvers
, based on @Freakish's code.
下面的代码生成了Django项目中所有完整的url模式的列表,包括基于@Freakish代码的嵌套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))