mirror of
https://github.com/django/django.git
synced 2025-06-01 09:39:12 +00:00
Refactored the internals of URL parsing to use less code
git-svn-id: http://code.djangoproject.com/svn/django/trunk@411 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
888cf1f889
commit
a55598cbdd
@ -1,4 +1,4 @@
|
|||||||
from django.core.urlresolvers import RegexURLMultiplePattern, RegexURLPattern
|
from django.core.urlresolvers import RegexURLPattern, RegexURLResolver
|
||||||
|
|
||||||
__all__ = ['handler404', 'handler500', 'include', 'patterns']
|
__all__ = ['handler404', 'handler500', 'include', 'patterns']
|
||||||
|
|
||||||
@ -11,7 +11,7 @@ def patterns(prefix, *tuples):
|
|||||||
pattern_list = []
|
pattern_list = []
|
||||||
for t in tuples:
|
for t in tuples:
|
||||||
if type(t[1]) == list:
|
if type(t[1]) == list:
|
||||||
pattern_list.append(RegexURLMultiplePattern(t[0], t[1][0]))
|
pattern_list.append(RegexURLResolver(t[0], t[1][0]))
|
||||||
else:
|
else:
|
||||||
pattern_list.append(RegexURLPattern(t[0], prefix and (prefix + '.' + t[1]) or t[1], *t[2:]))
|
pattern_list.append(RegexURLPattern(t[0], prefix and (prefix + '.' + t[1]) or t[1], *t[2:]))
|
||||||
return pattern_list
|
return pattern_list
|
||||||
|
@ -51,8 +51,7 @@ class BaseHandler:
|
|||||||
if response:
|
if response:
|
||||||
return response
|
return response
|
||||||
|
|
||||||
conf_module = __import__(ROOT_URLCONF, '', '', [''])
|
resolver = urlresolvers.RegexURLResolver(r'^/', ROOT_URLCONF)
|
||||||
resolver = urlresolvers.RegexURLResolver(conf_module.urlpatterns)
|
|
||||||
try:
|
try:
|
||||||
callback, param_dict = resolver.resolve(path)
|
callback, param_dict = resolver.resolve(path)
|
||||||
# Apply view middleware
|
# Apply view middleware
|
||||||
@ -65,8 +64,7 @@ class BaseHandler:
|
|||||||
if DEBUG:
|
if DEBUG:
|
||||||
return self.get_technical_error_response(is404=True)
|
return self.get_technical_error_response(is404=True)
|
||||||
else:
|
else:
|
||||||
resolver = urlresolvers.Error404Resolver(conf_module.handler404)
|
callback, param_dict = resolver.resolve404()
|
||||||
callback, param_dict = resolver.resolve()
|
|
||||||
return callback(request, **param_dict)
|
return callback(request, **param_dict)
|
||||||
except db.DatabaseError:
|
except db.DatabaseError:
|
||||||
db.db.rollback()
|
db.db.rollback()
|
||||||
@ -76,7 +74,7 @@ class BaseHandler:
|
|||||||
subject = 'Database error (%s IP)' % (request.META['REMOTE_ADDR'] in INTERNAL_IPS and 'internal' or 'EXTERNAL')
|
subject = 'Database error (%s IP)' % (request.META['REMOTE_ADDR'] in INTERNAL_IPS and 'internal' or 'EXTERNAL')
|
||||||
message = "%s\n\n%s" % (self._get_traceback(), request)
|
message = "%s\n\n%s" % (self._get_traceback(), request)
|
||||||
mail_admins(subject, message, fail_silently=True)
|
mail_admins(subject, message, fail_silently=True)
|
||||||
return self.get_friendly_error_response(request, conf_module)
|
return self.get_friendly_error_response(request, resolver)
|
||||||
except exceptions.PermissionDenied:
|
except exceptions.PermissionDenied:
|
||||||
return httpwrappers.HttpResponseForbidden('<h1>Permission denied</h1>')
|
return httpwrappers.HttpResponseForbidden('<h1>Permission denied</h1>')
|
||||||
except: # Handle everything else, including SuspiciousOperation, etc.
|
except: # Handle everything else, including SuspiciousOperation, etc.
|
||||||
@ -90,16 +88,15 @@ class BaseHandler:
|
|||||||
request_repr = "Request repr() unavailable"
|
request_repr = "Request repr() unavailable"
|
||||||
message = "%s\n\n%s" % (self._get_traceback(), request_repr)
|
message = "%s\n\n%s" % (self._get_traceback(), request_repr)
|
||||||
mail_admins(subject, message, fail_silently=True)
|
mail_admins(subject, message, fail_silently=True)
|
||||||
return self.get_friendly_error_response(request, conf_module)
|
return self.get_friendly_error_response(request, resolver)
|
||||||
|
|
||||||
def get_friendly_error_response(self, request, conf_module):
|
def get_friendly_error_response(self, request, resolver):
|
||||||
"""
|
"""
|
||||||
Returns an HttpResponse that displays a PUBLIC error message for a
|
Returns an HttpResponse that displays a PUBLIC error message for a
|
||||||
fundamental database or coding error.
|
fundamental database or coding error.
|
||||||
"""
|
"""
|
||||||
from django.core import urlresolvers
|
from django.core import urlresolvers
|
||||||
resolver = urlresolvers.Error404Resolver(conf_module.handler500)
|
callback, param_dict = resolver.resolve500()
|
||||||
callback, param_dict = resolver.resolve()
|
|
||||||
return callback(request, **param_dict)
|
return callback(request, **param_dict)
|
||||||
|
|
||||||
def get_technical_error_response(self, is404=False):
|
def get_technical_error_response(self, is404=False):
|
||||||
|
@ -18,13 +18,14 @@ def get_mod_func(callback):
|
|||||||
|
|
||||||
class RegexURLPattern:
|
class RegexURLPattern:
|
||||||
def __init__(self, regex, callback, default_args=None):
|
def __init__(self, regex, callback, default_args=None):
|
||||||
self.regex = re.compile(regex)
|
# regex is a string representing a regular expression.
|
||||||
# callback is something like 'foo.views.news.stories.story_detail',
|
# callback is something like 'foo.views.news.stories.story_detail',
|
||||||
# which represents the path to a module and a view function name.
|
# which represents the path to a module and a view function name.
|
||||||
|
self.regex = re.compile(regex)
|
||||||
self.callback = callback
|
self.callback = callback
|
||||||
self.default_args = default_args or {}
|
self.default_args = default_args or {}
|
||||||
|
|
||||||
def search(self, path):
|
def resolve(self, path):
|
||||||
match = self.regex.search(path)
|
match = self.regex.search(path)
|
||||||
if match:
|
if match:
|
||||||
args = dict(match.groupdict(), **self.default_args)
|
args = dict(match.groupdict(), **self.default_args)
|
||||||
@ -43,56 +44,44 @@ class RegexURLPattern:
|
|||||||
except AttributeError, e:
|
except AttributeError, e:
|
||||||
raise ViewDoesNotExist, "Tried %s in module %s. Error was: %s" % (func_name, mod_name, str(e))
|
raise ViewDoesNotExist, "Tried %s in module %s. Error was: %s" % (func_name, mod_name, str(e))
|
||||||
|
|
||||||
class RegexURLMultiplePattern:
|
class RegexURLResolver:
|
||||||
def __init__(self, regex, urlconf_module):
|
def __init__(self, regex, urlconf_name):
|
||||||
|
# regex is a string representing a regular expression.
|
||||||
|
# urlconf_name is a string representing the module containing urlconfs.
|
||||||
self.regex = re.compile(regex)
|
self.regex = re.compile(regex)
|
||||||
# urlconf_module is a string representing the module containing urlconfs.
|
self.urlconf_name = urlconf_name
|
||||||
self.urlconf_module = urlconf_module
|
|
||||||
|
|
||||||
def search(self, path):
|
def resolve(self, path):
|
||||||
match = self.regex.search(path)
|
match = self.regex.search(path)
|
||||||
if match:
|
if match:
|
||||||
new_path = path[match.end():]
|
new_path = path[match.end():]
|
||||||
try: # Lazily load self.url_patterns.
|
|
||||||
self.url_patterns
|
|
||||||
except AttributeError:
|
|
||||||
self.url_patterns = self.get_url_patterns()
|
|
||||||
for pattern in self.url_patterns:
|
for pattern in self.url_patterns:
|
||||||
sub_match = pattern.search(new_path)
|
sub_match = pattern.resolve(new_path)
|
||||||
if sub_match:
|
if sub_match:
|
||||||
return sub_match
|
return sub_match
|
||||||
|
# None of the regexes matched, so raise a 404.
|
||||||
|
raise Http404, "Tried all URL patterns but didn't find a match for %r" % path
|
||||||
|
|
||||||
def get_url_patterns(self):
|
def _get_urlconf_module(self):
|
||||||
return __import__(self.urlconf_module, '', '', ['']).urlpatterns
|
self.urlconf_module = __import__(self.urlconf_name, '', '', [''])
|
||||||
|
return self.urlconf_module
|
||||||
|
urlconf_module = property(_get_urlconf_module)
|
||||||
|
|
||||||
class RegexURLResolver:
|
def _get_url_patterns(self):
|
||||||
def __init__(self, url_patterns):
|
self.url_patterns = self.urlconf_module.urlpatterns
|
||||||
# url_patterns is a list of RegexURLPattern or RegexURLMultiplePattern objects.
|
return self.url_patterns
|
||||||
self.url_patterns = url_patterns
|
url_patterns = property(_get_url_patterns)
|
||||||
|
|
||||||
def resolve(self, app_path):
|
def _resolve_special(self, view_type):
|
||||||
# app_path is the full requested Web path. This is assumed to have a
|
callback = getattr(self.urlconf_module, 'handler%s' % view_type)
|
||||||
# leading slash but doesn't necessarily have a trailing slash.
|
mod_name, func_name = get_mod_func(callback)
|
||||||
# Examples:
|
|
||||||
# "/news/2005/may/"
|
|
||||||
# "/news/"
|
|
||||||
# "/polls/latest"
|
|
||||||
# A home (root) page is represented by "/".
|
|
||||||
app_path = app_path[1:] # Trim leading slash.
|
|
||||||
for pattern in self.url_patterns:
|
|
||||||
match = pattern.search(app_path)
|
|
||||||
if match:
|
|
||||||
return match
|
|
||||||
# None of the regexes matched, so raise a 404.
|
|
||||||
raise Http404, "Tried all URL patterns but didn't find a match for %r" % app_path
|
|
||||||
|
|
||||||
class Error404Resolver:
|
|
||||||
def __init__(self, callback):
|
|
||||||
self.callback = callback
|
|
||||||
|
|
||||||
def resolve(self):
|
|
||||||
mod_name, func_name = get_mod_func(self.callback)
|
|
||||||
try:
|
try:
|
||||||
return getattr(__import__(mod_name, '', '', ['']), func_name), {}
|
return getattr(__import__(mod_name, '', '', ['']), func_name), {}
|
||||||
except (ImportError, AttributeError), e:
|
except (ImportError, AttributeError), e:
|
||||||
raise ViewDoesNotExist, "Tried %s. Error was: %s" % (self.callback, str(e))
|
raise ViewDoesNotExist, "Tried %s. Error was: %s" % (callback, str(e))
|
||||||
|
|
||||||
|
def resolve404(self):
|
||||||
|
return self._resolve_special('404')
|
||||||
|
|
||||||
|
def resolve500(self):
|
||||||
|
return self._resolve_special('500')
|
||||||
|
Loading…
x
Reference in New Issue
Block a user