Ticket #4566: reverse-speedup2.diff
File reverse-speedup2.diff, 4.4 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 … … 129 148 def _get_callback(self): 130 149 if self._callback is not None: 131 150 return self._callback 132 mod_name, func_name = get_mod_func(self._callback_str)133 151 try: 134 self._callback = getattr(__import__(mod_name, {}, {}, ['']), func_name)152 self._callback = make_callable(self._callback_str) 135 153 except ImportError, e: 136 154 raise ViewDoesNotExist, "Could not import %s. Error was: %s" % (mod_name, str(e)) 137 155 except AttributeError, e: … … 160 178 self.urlconf_name = urlconf_name 161 179 self.callback = None 162 180 self.default_kwargs = default_kwargs or {} 181 self.reverse_dict = {} 182 183 for pattern in reversed(self.urlconf_module.urlpatterns): 184 if isinstance(pattern, RegexURLResolver): 185 for key, value in pattern.reverse_dict.iteritems(): 186 self.reverse_dict[key] = (pattern,) + value 187 else: 188 self.reverse_dict[pattern.callback] = (pattern,) 189 self.reverse_dict[pattern.name] = (pattern,) 163 190 164 191 def resolve(self, path): 165 192 tried = [] … … 209 236 return self._resolve_special('500') 210 237 211 238 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 239 try: 240 lookup_view = make_callable(lookup_view) 241 except (ImportError, AttributeError): 242 raise NoReverseMatch 243 if lookup_view in self.reverse_dict: 244 url_parts = (reverse_helper(part.regex, *args, **kwargs) for part in self.reverse_dict[lookup_view]) 245 return ''.join(url_parts) 230 246 raise NoReverseMatch 231 247 232 248 def reverse_helper(self, lookup_view, *args, **kwargs): … … 234 250 result = reverse_helper(self.regex, *args, **kwargs) 235 251 return result + sub_match 236 252 253 callable_cache = {} 254 def make_callable(lookup_view): 255 if not callable(lookup_view): 256 mod_name, func_name = get_mod_func(lookup_view) 257 if func_name != '': 258 lookup_view = getattr(__import__(mod_name, {}, {}, ['']), func_name) 259 return lookup_view 260 make_callable = cacheable(make_callable, callable_cache) 261 237 262 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) 263 resolver = get_resolver(urlconf) 242 264 return resolver.resolve(path) 243 265 244 266 def reverse(viewname, urlconf=None, args=None, kwargs=None): 245 267 args = args or [] 246 268 kwargs = kwargs or {} 247 if urlconf is None: 248 from django.conf import settings 249 urlconf = settings.ROOT_URLCONF 250 resolver = RegexURLResolver(r'^/', urlconf) 269 resolver = get_resolver(urlconf) 251 270 return '/' + resolver.reverse(viewname, *args, **kwargs)