forked from raiderrobert/django-multiurl
-
Notifications
You must be signed in to change notification settings - Fork 1
/
multiurl.py
79 lines (65 loc) · 2.7 KB
/
multiurl.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
from __future__ import unicode_literals
from django.core import urlresolvers
from django.http import HttpResponseNotAllowed
class ContinueResolving(Exception):
pass
def multiurl(*urls, **kwargs):
exceptions = kwargs.get('catch', (ContinueResolving,))
return MultiRegexURLResolver(urls, exceptions)
class MultiRegexURLResolver(urlresolvers.RegexURLResolver):
def __init__(self, urls, exceptions):
super(MultiRegexURLResolver, self).__init__('', None)
self._urls = urls
self._exceptions = exceptions
@property
def url_patterns(self):
return self._urls
def resolve(self, path):
tried = []
matched = []
patterns_matched = []
# This is a simplified version of RegexURLResolver. It doesn't
# support a regex prefix, and it doesn't need to handle include(),
# so it's simplier, but otherwise this is mostly a copy/paste.
try:
for pattern in self.url_patterns:
sub_match = pattern.resolve(path)
if sub_match:
# Here's the part that's different: instead of returning the
# first match, build up a list of all matches.
rm = urlresolvers.ResolverMatch(sub_match.func, sub_match.args, sub_match.kwargs, sub_match.url_name)
matched.append(rm)
patterns_matched.append([pattern])
tried.append([pattern])
except urlresolvers.Resolver404 as e:
pass
if matched:
return MultiResolverMatch(matched, self._exceptions, patterns_matched, path)
raise urlresolvers.Resolver404({'tried': tried, 'path': path})
class MultiResolverMatch(object):
def __init__(self, matches, exceptions, patterns_matched, path):
self.matches = matches
self.exceptions = exceptions
self.patterns_matched = patterns_matched
self.path = path
# Attributes to emulate ResolverMatch
self.kwargs = {}
self.args = ()
self.url_name = None
self.app_names = []
self.app_name = None
self.namespaces = []
@property
def func(self):
def multiview(request):
for i, match in enumerate(self.matches):
try:
response = match.func(request, *match.args, **match.kwargs)
if type(response) == HttpResponseNotAllowed:
continue
return response
except self.exceptions:
continue
raise urlresolvers.Resolver404({'tried': self.patterns_matched, 'path': self.path})
multiview.multi_resolver_match = self
return multiview