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:
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
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
.
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.
2👍
There are several javascript reverse
implementations out there.
http://djangojs.readthedocs.org/en/latest/djangojs.html#reverse-urls
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.
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.
The code iterates over every pattern removing the ?P
from each argument subregex so you could just replace them with .*
.
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.
- Django settings Unknown parameters: TEMPLATE_DEBUG
- Is there a Django ModelField that allows for multiple choices, aside from ManyToMany?
- Dynamic database tables in django
- Render current status only on template in StreamingHttpResponse in Django
- Using Django Admin Actions to send bulk emails
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]
- Invalid block tag: expected 'elif', 'else' or 'endif'
- Specifying Readonly access for Django.db connection object
- Is it possible to add SQL comments to a query built with the ORM?
1👍
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.
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))
0👍
As far as I understood, you want to be able to return the regex expression (and not the url) of a given view.
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).
So, I think that you can
- reverse search the view plus namespace
- get the tuple of that view from the tuple of tuples urlpatterns
- return _regex of the first argument,
LocaleRegexProvider._regex
(or regex()), of the tuple respective to the view.
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: Display a custom error message for admin validation error
- GenericForeignKey and Admin in Django
- Is it possible to force queryset evaluation while keeping it a queryset
- Django ajax error response best practice
- Making transient (non-database) attributes in Django model available to template