@@ -245,6 +245,10 @@ def __init__(self, regex, urlconf_name, default_kwargs=None, app_name=None, name
245245 self ._reverse_dict = {}
246246 self ._namespace_dict = {}
247247 self ._app_dict = {}
248+ # set of dotted paths to all functions and classes that are used in
249+ # urlpatterns
250+ self ._callback_strs = set ()
251+ self ._populated = False
248252
249253 def __repr__ (self ):
250254 if isinstance (self .urlconf_name , list ) and len (self .urlconf_name ):
@@ -262,6 +266,15 @@ def _populate(self):
262266 apps = {}
263267 language_code = get_language ()
264268 for pattern in reversed (self .url_patterns ):
269+ if hasattr (pattern , '_callback_str' ):
270+ self ._callback_strs .add (pattern ._callback_str )
271+ elif hasattr (pattern , '_callback' ):
272+ callback = pattern ._callback
273+ if not hasattr (callback , '__name__' ):
274+ lookup_str = callback .__module__ + "." + callback .__class__ .__name__
275+ else :
276+ lookup_str = callback .__module__ + "." + callback .__name__
277+ self ._callback_strs .add (lookup_str )
265278 p_pattern = pattern .regex .pattern
266279 if p_pattern .startswith ('^' ):
267280 p_pattern = p_pattern [1 :]
@@ -280,6 +293,7 @@ def _populate(self):
280293 namespaces [namespace ] = (p_pattern + prefix , sub_pattern )
281294 for app_name , namespace_list in pattern .app_dict .items ():
282295 apps .setdefault (app_name , []).extend (namespace_list )
296+ self ._callback_strs .update (pattern ._callback_strs )
283297 else :
284298 bits = normalize (p_pattern )
285299 lookups .appendlist (pattern .callback , (bits , p_pattern , pattern .default_args ))
@@ -288,6 +302,7 @@ def _populate(self):
288302 self ._reverse_dict [language_code ] = lookups
289303 self ._namespace_dict [language_code ] = namespaces
290304 self ._app_dict [language_code ] = apps
305+ self ._populated = True
291306
292307 @property
293308 def reverse_dict (self ):
@@ -387,8 +402,12 @@ def _reverse_with_prefix(self, lookup_view, _prefix, *args, **kwargs):
387402 text_args = [force_text (v ) for v in args ]
388403 text_kwargs = dict ((k , force_text (v )) for (k , v ) in kwargs .items ())
389404
405+ if not self ._populated :
406+ self ._populate ()
407+
390408 try :
391- lookup_view = get_callable (lookup_view , True )
409+ if lookup_view in self ._callback_strs :
410+ lookup_view = get_callable (lookup_view , True )
392411 except (ImportError , AttributeError ) as e :
393412 raise NoReverseMatch ("Error importing '%s': %s." % (lookup_view , e ))
394413 possibilities = self .reverse_dict .getlist (lookup_view )
0 commit comments