Ticket #4566: reverse-speedup.diff
File reverse-speedup.diff, 3.9 KB (added by , 17 years ago) |
---|
-
core/urlresolvers.py
11 11 from django.core.exceptions import ImproperlyConfigured, ViewDoesNotExist 12 12 import re 13 13 14 def cacheable(func, cache): 15 def wrapper(arg): 16 if arg in cache: 17 return cache[arg] 18 19 result = func(arg) 20 cache[arg] = result 21 return result 22 return wrapper 23 24 resolver_cache = {} 25 26 def get_resolver(urlconf): 27 if urlconf is None: 28 from django.conf import settings 29 urlconf = settings.ROOT_URLCONF 30 return RegexURLResolver(r'^/', urlconf) 31 get_resolver = cacheable(get_resolver, resolver_cache) 32 14 33 class Resolver404(Http404): 15 34 pass 16 35 … … 160 179 self.urlconf_name = urlconf_name 161 180 self.callback = None 162 181 self.default_kwargs = default_kwargs or {} 182 self.reverse_dict = {} 183 184 for pattern in reversed(self.urlconf_module.urlpatterns): 185 if isinstance(pattern, RegexURLResolver): 186 for key, value in pattern.reverse_dict.iteritems(): 187 self.reverse_dict[key] = (pattern,) + value 188 else: 189 self.reverse_dict[pattern.callback] = (pattern,) 190 self.reverse_dict[pattern.name] = (pattern,) 163 191 164 192 def resolve(self, path): 165 193 tried = [] … … 209 237 return self._resolve_special('500') 210 238 211 239 def reverse(self, lookup_view, *args, **kwargs): 212 if not callable(lookup_view): 213 mod_name, func_name = get_mod_func(lookup_view) 214 try: 215 lookup_view = getattr(__import__(mod_name, {}, {}, ['']), func_name) 216 except (ImportError, AttributeError): 217 if func_name != '': 218 raise NoReverseMatch 219 for pattern in self.urlconf_module.urlpatterns: 220 if isinstance(pattern, RegexURLResolver): 221 try: 222 return pattern.reverse_helper(lookup_view, *args, **kwargs) 223 except NoReverseMatch: 224 continue 225 elif pattern.callback == lookup_view or pattern.name == lookup_view: 226 try: 227 return pattern.reverse_helper(*args, **kwargs) 228 except NoReverseMatch: 229 continue 240 lookup_view = make_callable(lookup_view) 241 if lookup_view in self.reverse_dict: 242 url_parts = (reverse_helper(part.regex, *args, **kwargs) for part in self.reverse_dict[lookup_view]) 243 return ''.join(url_parts) 230 244 raise NoReverseMatch 231 245 232 246 def reverse_helper(self, lookup_view, *args, **kwargs): … … 234 248 result = reverse_helper(self.regex, *args, **kwargs) 235 249 return result + sub_match 236 250 251 callable_cache = {} 252 def make_callable(lookup_view): 253 if not callable(lookup_view): 254 mod_name, func_name = get_mod_func(lookup_view) 255 if func_name != '': 256 try: 257 lookup_view = getattr(__import__(mod_name, {}, {}, ['']), func_name) 258 except (ImportError, AttributeError): 259 if func_name != '': 260 raise NoReverseMatch 261 return lookup_view 262 make_callable = cacheable(make_callable, callable_cache) 263 237 264 def resolve(path, urlconf=None): 238 if urlconf is None: 239 from django.conf import settings 240 urlconf = settings.ROOT_URLCONF 241 resolver = RegexURLResolver(r'^/', urlconf) 265 resolver = get_resolver(urlconf) 242 266 return resolver.resolve(path) 243 267 244 268 def reverse(viewname, urlconf=None, args=None, kwargs=None): 245 269 args = args or [] 246 270 kwargs = kwargs or {} 247 if urlconf is None: 248 from django.conf import settings 249 urlconf = settings.ROOT_URLCONF 250 resolver = RegexURLResolver(r'^/', urlconf) 271 resolver = get_resolver(urlconf) 251 272 return '/' + resolver.reverse(viewname, *args, **kwargs)