def can_url(user, view): """ Tests whether the given user would have access to the view. The view can be a callable, importable text path or a view name, possibly with the namespace prefix ('namespace:view_name'). The view function must be decorated with the can_url_func (that's what UrlPatterns class does). """ if ':' not in view: view = get_callable(view) if not callable(view): callbacks = get_all_callbacks(get_urlconf()) if view not in callbacks: raise NoReverseMatch("Reverse for '%s' not found." % view) view = callbacks[view] if not hasattr(view, 'can_url_func'): raise NoReverseMatch( "Reverse for '%s' is not decorated with permissions." % view) try: return view.can_url_func(user) except PermissionDenied: return False
def reverse_subdomain(name, args=(), kwargs=None): if args and kwargs: raise ValueError("Don't mix *args and **kwargs in call to reverse()!") if kwargs is None: kwargs = {} try: subdomain = settings.SUBDOMAINS[name] except KeyError: raise NoReverseMatch("No subdomain called %s exists" % name) unicode_args = [force_unicode(x) for x in args] unicode_kwargs = dict([(k, force_unicode(v)) for (k, v) in kwargs.items()]) for result, params in normalize(subdomain['regex']): if args: if len(args) != len(params): continue candidate = result % dict(zip(params, unicode_args)) else: if set(kwargs.keys()) != set(params): continue candidate = result % unicode_kwargs if re.match(subdomain['regex'], candidate, re.UNICODE): return candidate raise NoReverseMatch( "Reverse subdomain for '%s' with arguments '%s' and keyword arguments " "'%s' not found." % (name, args, kwargs))
def reverse_resource(resource, viewname, args=None, kwargs=None, **extra): """ Generate the URL for the view specified as viewname of the object specified as resource. """ kwargs = kwargs or {} parent = resource while parent is not None: if not hasattr(parent, 'get_url_kwarg'): return NoReverseMatch('Cannot get URL kwarg for %s' % resource) # pragma: no cover if parent.is_versioned and not parent.is_head: from core.collections.models import Collection from core.sources.models import Source if isinstance(parent, (Source, Collection)): head = parent.get_latest_version() else: head = parent.head if head: kwargs.update({head.get_url_kwarg(): head.mnemonic}) kwargs.update({parent.get_url_kwarg(): parent.version}) parent_resource_url_kwarg = parent.get_resource_url_kwarg() if parent_resource_url_kwarg not in kwargs: kwargs.update({parent_resource_url_kwarg: parent.mnemonic}) else: kwargs.update({parent.get_url_kwarg(): parent.mnemonic}) parent = parent.parent if hasattr(parent, 'parent') else None allowed_kwargs = get_kwargs_for_view(viewname) for key in kwargs.copy(): if key not in allowed_kwargs: kwargs.pop(key) return reverse(viewname=viewname, args=args, kwargs=kwargs, **extra)
def ensure_node_has_url_property(node): """Ensure that a node has a url property""" if 'url' not in node: try: route = node['route'] if route != '#': url = reverse(route) else: url = '#' except KeyError as key_error: error_message = ( "The route key must be provided for the node." " If you do not have a valid route yet you can use '#' as a placeholder." " If you have Whitelisting turned on, be sure to" " add an entry for '#' to the whitelist." " Missing key was: {0}" ).format(key_error) raise KeyError(error_message) from key_error except NoReverseMatch as reverse_error: error_message = ( "The node with the route '{0}' is not a valid route." " If you do not have a valid route yet you can use '#' as a placeholder." " If you have Whitelisting turned on, be sure to" " add an entry for '#' to the whitelist." " Exception Message: {1}" ).format(route, reverse_error) raise NoReverseMatch(error_message) from reverse_error node['url'] = url
def get_formatted_url(url_name): try: # No current_app detection, because there could be injected urls from different apps / namespaces. return reverse(url_name) except NoReverseMatch: # Url regex pattern has named parameters. Translate these to Javascript sprintf() library format. urlresolver = get_resolver(None) urls = get_sprintf_urls(urlresolver, url_name) if len(urls) == 1: return '{}{}'.format(get_script_prefix(), urls[0]) elif len(urls) == 0: raise NoReverseMatch('Cannot find sprintf formatted url for %s' % url_name) else: raise NoReverseMatch('Multiple sprintf formatted url for %s' % url_name)
def reverse_any(viewnames, urlconf=None, args=None, kwargs=None, *fargs, **fkwargs): """ Tries reversing a list of viewnames with the same arguments, and returns the first result where no ``NoReverseMatch`` exception is raised. Usage:: url = reverse_any(( 'blog:article-detail', 'articles:article-detail', ), kwargs={'slug': 'article-slug'}) """ for viewname in viewnames: try: return reverse(viewname, urlconf, args, kwargs, *fargs, **fkwargs) except NoReverseMatch: pass raise NoReverseMatch( "Reverse for any of '%s' with arguments '%s' and keyword arguments" " '%s' not found." % ("', '".join(viewnames), args or [], kwargs or {}))
def setUp(self): """Define the test client and other test variables.""" self.client = APIClient() self.task_data = {'name': 'Go to Shiraz'} self.response = self.client.post(NoReverseMatch('create'), self.task_data, format="json")
def reverse(feature_name, **kwargs): feature_schema = schema.get_schema() try: feature = feature_schema[feature_name] except KeyError: raise NoReverseMatch(feature_name) else: return substitute(feature['coerced_url'], kwargs)
def app_reverse(viewname, urlconf=None, args=None, kwargs=None, *vargs, **vkwargs): """ Reverse URLs from application contents Works almost like Django's own reverse() method except that it resolves URLs from application contents. The second argument, ``urlconf``, has to correspond to the URLconf parameter passed in the ``APPLICATIONS`` list to ``Page.create_content_type``:: app_reverse('mymodel-detail', 'myapp.urls', args=...) or app_reverse('mymodel-detail', 'myapp.urls', kwargs=...) The second argument may also be a request object if you want to reverse an URL belonging to the current application content. """ # First parameter might be a request instead of an urlconf path, so # we'll try to be helpful and extract the current urlconf from it extra_context = getattr(urlconf, "_feincms_extra_context", {}) appconfig = extra_context.get("app_config", {}) urlconf = appconfig.get("urlconf_path", urlconf) appcontent_class = ApplicationContent._feincms_content_models[0] cache_key = appcontent_class.app_reverse_cache_key(urlconf) url_prefix = cache.get(cache_key) if url_prefix is None: content = appcontent_class.closest_match(urlconf) if content is not None: if urlconf in appcontent_class.ALL_APPS_CONFIG: # We have an overridden URLconf app_config = appcontent_class.ALL_APPS_CONFIG[urlconf] urlconf = app_config["config"].get("urls", urlconf) prefix = content.parent.get_absolute_url() prefix += "/" if prefix[-1] != "/" else "" url_prefix = (urlconf, prefix) cache.set(cache_key, url_prefix, timeout=APP_REVERSE_CACHE_TIMEOUT) if url_prefix: # vargs and vkwargs are used to send through additional parameters # which are uninteresting to us (such as current_app) prefix = get_script_prefix() try: set_script_prefix(url_prefix[1]) return reverse( viewname, url_prefix[0], args=args, kwargs=kwargs, *vargs, **vkwargs ) finally: set_script_prefix(prefix) raise NoReverseMatch("Unable to find ApplicationContent for %r" % urlconf)
def get_permissions_from_node(node): """ Gets the permissions required from the node by using either the 'route' or 'url' key on the node to determine the associated view for the route/url. Then checks the view to see if it contains properties for the required permissions and returns them if found. """ permissions = node.get('permissions', None) one_of_permissions = node.get('one_of_permissions', None) if permissions is not None or one_of_permissions is not None: return permissions or [], one_of_permissions or [] view = None try: route = node['route'] url_with_hash = node.get('url', None) url = url_with_hash.split('#')[0] if url_with_hash else None if route != '#': view = resolve(reverse(route)) elif url and url != '': view = resolve(url) except KeyError as key_error: error_message = ( "The route key must be provided for the node." " If you do not have a valid route yet you can use '#' as a placeholder." " If you have Whitelisting turned on, be sure to add an entry for '#' to the whitelist." " Missing key was: {0}" ).format(key_error) raise KeyError(error_message) from key_error except NoReverseMatch as reverse_error: error_message = ( "The node with the route '{0}' is not a valid route." " If you do not have a valid route yet you can use '#' as a placeholder." " If you have Whitelisting turned on, be sure to add an entry for '#' to the whitelist." " Exception Message: {1}" ).format(route, reverse_error) raise NoReverseMatch(error_message) from reverse_error if view: view_class = getattr(view.func, 'view_class', None) if view_class: permissions = getattr(view_class, 'permission_required', []) one_of_permissions = getattr( view_class, 'permission_required_one', [] ) else: permissions = getattr(view.func, 'permissions', []) one_of_permissions = getattr(view.func, 'one_of_permissions', []) return permissions or [], one_of_permissions or []
def legaltext_url(context, name): legaltext = LegalText.objects.filter(Q(url_name=name) | Q(slug=name)).first() silent = getattr(settings, 'LEGALTEXT_SILENCE_TEMPLATE_ERRORS', False) if not legaltext: if silent: return '' raise NoReverseMatch( _('Legaltext with slug/name: {0} does not exist').format(name)) return legaltext.get_absolute_url()
def reverse_path(subdomain, view, args=(), kwargs=None): if kwargs is None: kwargs = {} try: urlconf = settings.SUBDOMAINS[subdomain]['urlconf'] except KeyError: raise NoReverseMatch("No subdomain called %s exists" % subdomain) return reverse(view, args=args, kwargs=kwargs, urlconf=urlconf)
def get_host(name=None): if name is None: try: name = settings.DEFAULT_HOST except AttributeError: raise ImproperlyConfigured("Missing DEFAULT_HOST setting") for host in get_host_patterns(): if host.name == name: return host raise NoReverseMatch("No host called '%s' exists" % name)
def reverse_host(host, args=None, kwargs=None): """ Given the host name and the appropriate parameters, reverses the host, e.g.:: >>> from django.conf import settings >>> settings.ROOT_HOSTCONF = 'mysite.hosts' >>> settings.PARENT_HOST = 'example.com' >>> from django_hosts.resolvers import reverse_host >>> reverse_host('with_username', args=('jezdez',)) 'jezdez.example.com' :param name: the name of the host as specified in the hostconf :param args: the host arguments to use to find a matching entry in the hostconf :param kwargs: similar to args but key value arguments :raises django.core.urlresolvers.NoReverseMatch: if no host matches :rtype: reversed hostname """ if args and kwargs: raise ValueError("Don't mix *args and **kwargs in call to reverse()!") args = args or () kwargs = kwargs or {} if not isinstance(host, host_cls): host = get_host(host) unicode_args = [force_text(x) for x in args] unicode_kwargs = dict( ((k, force_text(v)) for (k, v) in dict.items(kwargs))) for result, params in normalize(host.regex): if args: if len(args) != len(params): continue candidate = result % dict(zip(params, unicode_args)) else: if set(kwargs.keys()) != set(params): continue candidate = result % unicode_kwargs if re.match(host.regex, candidate, re.UNICODE): # pragma: no cover parent_host = getattr(settings, 'PARENT_HOST', '').lstrip('.') if parent_host: # only add the parent host when needed (aka www-less domain) if candidate and candidate != parent_host: candidate = '%s.%s' % (candidate, parent_host) else: candidate = parent_host return candidate raise NoReverseMatch("Reverse host for '%s' with arguments '%s' " "and keyword arguments '%s' not found." % (host.name, args, kwargs))
def meta(self): """ Meta info for uploader instance. """ try: args = ['__namespace__', '__prefix__'] upload_url = self.reverse('upload', args=args) clipboard_flush_url = self.reverse('clipboard_flush', args=args) except NoReverseMatch, e: error = ('%s\nPlease check out you hooked up %s.urls somewere in' ' your urlconf.' % (e.message, self.__class__.__name__)) raise NoReverseMatch(error)
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]: inner_urlresolver = get_ns_resolver( inner_ns_path, inner_urlresolver, tuple(urlresolver.pattern.converters.items())) 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 __call__(self, feature_name, kwargs=None, **extra): feature_schema = schema.get_schema() try: feature_def = feature_schema[feature_name] except KeyError: raise NoReverseMatch(feature_name) else: path = urls.substitute(feature_def['coerced_url'], kwargs or {}) method = feature_def['http_method_name'] return getattr(self, method)( path=path, **extra, )
def get_formatted_url(url_name): try: return reverse(url_name) except NoReverseMatch: # Url regex pattern has named parameters. Translate these to Javascript sprintf() library format. urlresolver = get_resolver(None) # Django 2.0 generates url_def tuples of 4 elements, < 2.0 - tuple of 3 elements. for url_def in urlresolver.reverse_dict.getlist(url_name): matches = url_def[0] for sprintf_url, _named_parameters in matches: return '{}{}'.format(get_script_prefix(), sprintf_url) raise NoReverseMatch('Cannot find sprintf formatted url for %s' % url_name)
def get_url(self, obj, view_name, request, format): """ Given an object, return the URL that hyperlinks to the object. May raise a `NoReverseMatch` if the `view_name` and `lookup_field` attributes are not configured to correctly match the URL conf. """ lookup_field = getattr(obj, self.lookup_field) kwargs = {self.lookup_field: lookup_field} try: return reverse(view_name, kwargs=kwargs, request=request, format=format) except NoReverseMatch: pass if self.pk_url_kwarg != "pk": # Only try pk if it has been explicitly set. # Otherwise, the default `lookup_field = "pk"` has us covered. pk = obj.pk kwargs = {self.pk_url_kwarg: pk} try: return reverse(view_name, kwargs=kwargs, request=request, format=format) except NoReverseMatch: pass slug = getattr(obj, self.slug_field, None) if slug is not None: # Only try slug if it corresponds to an attribute on the object. kwargs = {self.slug_url_kwarg: slug} try: ret = reverse(view_name, kwargs=kwargs, request=request, format=format) if self.slug_field == "slug" and self.slug_url_kwarg == "slug": # If the lookup succeeds using the default slug params, # then `slug_field` is being used implicitly, and we # we need to warn about the pending deprecation. msg = "Implicit slug field hyperlinked fields are pending deprecation." \ "You should set `lookup_field=slug` on the HyperlinkedRelatedField." warnings.warn(msg, PendingDeprecationWarning, stacklevel=2) return ret except NoReverseMatch: pass raise NoReverseMatch()
def get_url(self, obj, view_name, request, format): """ Given an object, return the URL that hyperlinks to the object. May raise a `NoReverseMatch` if the `view_name` and `lookup_field` attributes are not configured to correctly match the URL conf. """ lookup_field = getattr(obj, self.lookup_field, None) kwargs = {self.lookup_field: lookup_field} kwargs.update(self.get_extra_url_kwargs(obj)) # Handle unsaved object case if lookup_field is None: return None try: return reverse(view_name, kwargs=kwargs, request=request, format=format) except NoReverseMatch: pass if self.pk_url_kwarg != 'pk': # Only try pk lookup if it has been explicitly set. # Otherwise, the default `lookup_field = 'pk'` has us covered. kwargs = {self.pk_url_kwarg: obj.pk} kwargs.update(self.get_extra_url_kwargs(obj)) try: return reverse(view_name, kwargs=kwargs, request=request, format=format) except NoReverseMatch: pass slug = getattr(obj, self.slug_field, None) if slug: # Only use slug lookup if a slug field exists on the model kwargs = {self.slug_url_kwarg: slug} kwargs.update(self.get_extra_url_kwargs(obj)) try: return reverse(view_name, kwargs=kwargs, request=request, format=format) except NoReverseMatch: pass raise NoReverseMatch()
def crud_inline_url(obj, inline, action, namespace=None): all_tried_names = [] try: nurl = utils.crud_url_name(type(inline), action, base_model=obj.__class__) if namespace: nurl = namespace + ':' + nurl if action in ['delete', 'update', 'detail']: url = reverse(nurl, kwargs={'model_id': obj.pk, 'pk': inline.pk}) else: url = reverse(nurl, kwargs={'model_id': obj.pk}) except NoReverseMatch as e: all_tried_names.append((nurl, e)) # it could be that base_model is a child class and thus # the url does not exist when the inline was only defined for a # parent class no_match = True for base in obj.__class__.__bases__: try: nurl = utils.crud_url_name(type(inline), action, base_model=base) if namespace: nurl = namespace + ':' + nurl if action in ['delete', 'update', 'detail']: url = reverse(nurl, kwargs={ 'model_id': obj.pk, 'pk': inline.pk }) else: url = reverse(nurl, kwargs={'model_id': obj.pk}) no_match = False except NoReverseMatch as e: all_tried_names.append((nurl, e)) if not no_match: break if no_match: raise NoReverseMatch('No reverse match was found for any of the following url_names: "'+\ '", "'.join(n[0] for n in all_tried_names) +'". These are the raised errors: ' +\ ", ".join("{}".format(n[1]) for n in all_tried_names) ) return url
def render(self, context): from django.urls import NoReverseMatch, reverse user = context['user'] output = '' icon_html = """ <ul class="navbar-nav mr-auto"> <li class="nav-item"> <a href="{}" class="nav-link"> <i class="fa fa-{}"></i> </a> </li> </ul> """ base_structure = """ <ul class="navbar-nav mr-auto"> {links} </ul> """ text_html = """ <li class="nav-item"> <a href="{}" class="nav-link"> {} </a> </li> """ constructed_links = '' for view in self.base_views: try: url = reverse(view[0]) except: raise NoReverseMatch(f"For reverse for '{view[0]}'") else: constructed_links += format_html( text_html, url, view[1]['verbose_name'] ) nav_item = mark_safe(base_structure.format(links=constructed_links)) if user.is_authenticated: if user.is_admin or user.is_staff: nav_item = format_html( nav_item, '/admin', 'Admin' ) output += nav_item return output
def resolve_url(model, view_name): """Tries to guess URL of a model. Use this only when you don't know in advance what the model type is (e.g. a subclass) and if the URL pattern is simple i.e no additional arguments other than the primary key field. The pattern is: If model is a class, not an instance, will just return view as-is. If the model is an instance, will automatically add the primary key as argument. Examples: {{ Post|resolve_url:"list" }} -> /posts/ {{ post|resolve_url:"list" }} -> /posts/ {{ post|resolve_url:"update" }} -> /posts/1234/~update/ Args: model (Model class or instance) view_name (str): name of the view Returns: str: url """ url_patterns = [ f"{model._meta.app_label}:{model._meta.model_name}_{view_name}", f"{model._meta.app_label}:{view_name}", ] url_args = [[]] if isinstance(model, Model): url_args.append([model.pk]) for pattern in url_patterns: for args in url_args: try: return reverse(pattern, args=args) except NoReverseMatch: pass raise NoReverseMatch(f"No URL pattern found for {model} {view_name}")
def _find_plugin_reverse(viewname, args, kwargs): from fluent_pages.extensions import page_type_pool plugins = page_type_pool.get_url_pattern_plugins() for plugin in plugins: try: url_end = plugin.get_url_resolver().reverse( viewname, *args, **kwargs) return plugin, url_end except NoReverseMatch: pass else: raise NoReverseMatch( "Reverse for application URL '{0}' with arguments '{1}' and keyword arguments '{2}' not found.\n" "Searched in URLconf and installed page type plugins ({3}) for URLs." .format( viewname, args, kwargs, ', '.join(x.__class__.__name__ for x in page_type_pool.get_plugins()) or "none"))
def view_on_site(self, obj): try: RegisteredSubject.objects.get( subject_identifier=obj.subject_identifier) except ObjectDoesNotExist: url = reverse(self.get_subject_listboard_url_name()) else: try: url = reverse( self.get_subject_dashboard_url_name(), kwargs=self.get_subject_dashboard_url_kwargs(obj), ) except NoReverseMatch as e: if callable(super().view_on_site): url = super().view_on_site(obj) else: raise NoReverseMatch( f"{e}. See subject_dashboard_url_name for {repr(self)}." ) return url
def test_get_page_url_view_sub(self, mock_reverse): mock_reverse.side_effect = [NoReverseMatch(), "/some_nice_url"] url = bootstrap_pagination.get_page_url( page_num=42, current_app='the_current_app', url_view_name='the_view', url_extra_args=["arg1"], url_extra_kwargs={"kwarg": "yes"}, url_param_name='page', url_get_params=django.http.QueryDict(""), url_anchor="derp") self.assertEqual(url, '/some_nice_url#derp') mock_reverse.assert_called_with('tests.the_view', args=['arg1'], current_app='the_current_app', kwargs={ 'kwarg': 'yes', 'page': 42 })
def parse_url(lookup_view): if not lookup_view: raise ValueError("No lookup_view") url = None try: url = reverse_with_params( viewname=lookup_view["viewname"], args=lookup_view.get("args", []), query_string=lookup_view.get("query_string", None), ) except KeyError: # assume we've been passed a url try: resolve(lookup_view) url = lookup_view except Exception: pass if url is None: logger.error("Reverse for '%s' not found." % lookup_view) raise NoReverseMatch("Reverse for '%s' not found." % lookup_view) return url
def reverse(self, *args, **kwargs): if self.raise_error: raise NoReverseMatch() return 'http://scheme-reversed/view'
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 urlconf_from_subdomain(name): try: return settings.SUBDOMAINS[name]['urlconf'] except KeyError: raise NoReverseMatch("No %r subdomain exists" % name)