def prepare_url_list(resolver, namespace_path='', namespace=''): for url_name in resolver.reverse_dict.keys(): if not isinstance(url_name, str): continue url_name = force_str(url_name) formated_patterns = [] for url_pattern in resolver.reverse_dict.getlist(url_name): for url_format, url_params in url_pattern[0]: formated_patterns.append({ 'pattern': namespace_path + url_format, 'params': url_params }) yield {'name': namespace + url_name, 'patterns': formated_patterns} for inner_ns, (inner_ns_path, inner_resolver) in resolver.namespace_dict.items(): inner_ns_path = namespace_path + inner_ns_path inner_ns = namespace + inner_ns + ':' if inner_ns_path: inner_resolver = urls.get_ns_resolver(inner_ns_path, inner_resolver, ()) inner_ns_path = '' for url_pattern in prepare_url_list(inner_resolver, inner_ns_path, inner_ns): yield url_pattern
def get_namespace_path_resolver(urlresolver, ns_path): for inner_ns, (inner_ns_path, inner_urlresolver) in \ urlresolver.namespace_dict.items(): if inner_ns == ns_path[0]: if hasattr(urlresolver, 'pattern'): inner_urlresolver = get_ns_resolver( inner_ns_path, inner_urlresolver, tuple(urlresolver.pattern.converters.items())) else: # Django 1.11. inner_urlresolver = get_ns_resolver(inner_ns_path, inner_urlresolver) if len(ns_path) == 1: return inner_urlresolver else: return get_namespace_path_resolver(inner_urlresolver, ns_path[1:]) raise NoReverseMatch('Cannot find namespace %s' ':'.join(ns_path))
def urltemplate_namespaces(viewname, current_app=None, *args, **kwargs): urlconf = urls.get_urlconf() resolver = urls.get_resolver(urlconf) prefix = urls.get_script_prefix() parts = viewname.split(':') parts.reverse() view = parts[0] path = parts[1:] resolved_path = [] ns_pattern = '' while path: ns = path.pop() # Lookup the name to see if it could be an app identifier try: app_list = resolver.app_dict[ns] # Yes! Path part matches an app in the current Resolver if current_app and current_app in app_list: # If we are reversing for a particular app, # use that namespace ns = current_app elif ns not in app_list: # The name isn't shared by one of the instances # (i.e., the default) so just pick the first instance # as the default. ns = app_list[0] except KeyError: pass try: extra, resolver = resolver.namespace_dict[ns] resolved_path.append(ns) ns_pattern = ns_pattern + extra except KeyError as key: if resolved_path: raise urls.NoReverseMatch( "%s is not a registered namespace inside '%s'" % (key, ':'.join(resolved_path))) else: raise urls.NoReverseMatch("%s is not a registered namespace" % key) if ns_pattern: resolver = urls.get_ns_resolver(ns_pattern, resolver) return urltemplate_with_prefix(resolver, view, prefix, *args, **kwargs)
def view_from_url(named_url): # noqa """ Finds and returns the view class from a named url """ # code below is `stolen` from django's reverse method. resolver = get_resolver(get_urlconf()) if type(named_url) in (list, tuple): named_url = named_url[0] parts = named_url.split(':') parts.reverse() view = parts[0] path = parts[1:] current_path = None resolved_path = [] ns_pattern = '' ns_converters = {} # if it's a local url permission already given, so we just return true if named_url.startswith('#'): class LocalUrlDummyView: @staticmethod def has_permission(user): return True return LocalUrlDummyView while path: ns = path.pop() current_ns = current_path.pop() if current_path else None # Lookup the name to see if it could be an app identifier try: app_list = resolver.app_dict[ns] # Yes! Path part matches an app in the current Resolver if current_ns and current_ns in app_list: # If we are reversing for a particular app, # use that namespace ns = current_ns elif ns not in app_list: # The name isn't shared by one of the instances # (i.e., the default) so just pick the first instance # as the default. ns = app_list[0] except KeyError: pass if ns != current_ns: current_path = None try: extra, resolver = resolver.namespace_dict[ns] resolved_path.append(ns) ns_pattern = ns_pattern + extra try: ns_converters.update(resolver.pattern.converters) except Exception: pass except KeyError as key: if resolved_path: raise NoReverseMatch( "%s is not a registered namespace inside '%s'" % (key, ':'.join(resolved_path))) else: raise NoReverseMatch("%s is not a registered namespace" % key) if ns_pattern: try: resolver = get_ns_resolver(ns_pattern, resolver, tuple(ns_converters.items())) except Exception: resolver = get_ns_resolver(ns_pattern, resolver) # custom code, get view from reverse_dict reverse_dict = resolver.reverse_dict.dict() for key, url_obj in reverse_dict.items(): if url_obj == reverse_dict[view] \ and key != view: module = importlib.import_module(key.__module__) return getattr(module, key.__name__)
def prepare_url_list(urlresolver, namespace_path='', namespace=''): """ returns list of tuples [(<url_name>, <url_patern_tuple> ), ...] """ exclude_ns = getattr(settings, 'JS_REVERSE_EXCLUDE_NAMESPACES', JS_EXCLUDE_NAMESPACES) include_only_ns = getattr(settings, 'JS_REVERSE_INCLUDE_ONLY_NAMESPACES', JS_INCLUDE_ONLY_NAMESPACES) if exclude_ns and include_only_ns: raise ImproperlyConfigured( 'Neither use JS_REVERSE_EXCLUDE_NAMESPACES nor JS_REVERSE_INCLUDE_ONLY_NAMESPACES setting' ) if namespace[:-1] in exclude_ns: return include_only_allow = True # include_only state variable if include_only_ns != []: # True mean that ns passed the test in_on_empty_ns = False in_on_is_in_list = False in_on_null = False # Test urls without ns if namespace == '' and '' in include_only_ns: in_on_empty_ns = True # check if nestead ns isn't subns of include_only ns # e.g. ns = "foo:bar" include_only = ["foo"] -> this ns will be used # works for ns = "lorem:ipsum:dolor" include_only = ["lorem:ipsum"] # ns "lorem" will be ignored but "lorem:ipsum" & "lorem:ipsum:.." won't for ns in include_only_ns: if ns != "" and namespace[:-1].startswith(ns): in_on_is_in_list = True break # Test if isn't used "\0" flag # use "foo\0" to add urls just from "foo" not from subns "foo:bar" if namespace[:-1] + '\0' in include_only_ns: in_on_null = True include_only_allow = in_on_empty_ns or in_on_is_in_list or in_on_null if include_only_allow: for url_name in urlresolver.reverse_dict.keys(): if isinstance(url_name, (text_type, str)): url_patterns = [] for url_pattern in urlresolver.reverse_dict.getlist(url_name): url_patterns += [[namespace_path + pat[0], pat[1]] for pat in url_pattern[0]] yield [namespace + url_name, url_patterns] for inner_ns, (inner_ns_path, inner_urlresolver) in \ urlresolver.namespace_dict.items(): inner_ns_path = namespace_path + inner_ns_path inner_ns = namespace + inner_ns + ':' # if we have inner_ns_path, reconstruct a new resolver so that we can # handle regex substitutions within the regex of a namespace. if inner_ns_path: args = [inner_ns_path, inner_urlresolver] # https://github.com/ierror/django-js-reverse/issues/65 if LooseVersion(django.get_version()) >= LooseVersion("2.0.6"): args.append(tuple(urlresolver.pattern.converters.items())) inner_urlresolver = urlresolvers.get_ns_resolver(*args) inner_ns_path = '' for x in prepare_url_list(inner_urlresolver, inner_ns_path, inner_ns): yield x
def prepare_url_list(urlresolver, namespace_path='', namespace=''): """ returns list of tuples [(<url_name>, <url_patern_tuple> ), ...] """ exclude_ns = getattr(settings, 'JS_REVERSE_EXCLUDE_NAMESPACES', JS_EXCLUDE_NAMESPACES) include_only_ns = getattr(settings, 'JS_REVERSE_INCLUDE_ONLY_NAMESPACES', JS_INCLUDE_ONLY_NAMESPACES) if exclude_ns and include_only_ns: raise ImproperlyConfigured( 'Neither use JS_REVERSE_EXCLUDE_NAMESPACES nor JS_REVERSE_INCLUDE_ONLY_NAMESPACES setting') if namespace[:-1] in exclude_ns: return include_only_allow = True # include_only state varible if include_only_ns != []: # True mean that ns passed the test in_on_empty_ns = False in_on_is_in_list = False in_on_null = False # Test urls without ns if namespace == '' and '' in include_only_ns: in_on_empty_ns = True # check if nestead ns isn't subns of include_only ns # e.g. ns = "foo:bar" include_only = ["foo"] -> this ns will be used # works for ns = "lorem:ipsum:dolor" include_only = ["lorem:ipsum"] # ns "lorem" will be ignored but "lorem:ipsum" & "lorem:ipsum:.." won't for ns in include_only_ns: if ns != "" and namespace[:-1].startswith(ns): in_on_is_in_list = True break # Test if isn't used "\0" flag # use "foo\0" to add urls just from "foo" not from subns "foo:bar" if namespace[:-1] + '\0' in include_only_ns: in_on_null = True include_only_allow = in_on_empty_ns or in_on_is_in_list or in_on_null if include_only_allow: for url_name in urlresolver.reverse_dict.keys(): if isinstance(url_name, (text_type, str)): url_patterns = [] for url_pattern in urlresolver.reverse_dict.getlist(url_name): url_patterns += [ [namespace_path + pat[0], pat[1]] for pat in url_pattern[0]] yield [namespace + url_name, url_patterns] for inner_ns, (inner_ns_path, inner_urlresolver) in \ urlresolver.namespace_dict.items(): inner_ns_path = namespace_path + inner_ns_path inner_ns = namespace + inner_ns + ':' # if we have inner_ns_path, reconstruct a new resolver so that we can # handle regex substitutions within the regex of a namespace. if inner_ns_path: args = [inner_ns_path, inner_urlresolver] # https://github.com/ierror/django-js-reverse/issues/65 if LooseVersion(django.get_version()) >= LooseVersion("2.0.6"): args.append(tuple(urlresolver.pattern.converters.items())) inner_urlresolver = urlresolvers.get_ns_resolver(*args) inner_ns_path = '' for x in prepare_url_list(inner_urlresolver, inner_ns_path, inner_ns): yield x