From 10e6ae20949028171fdfcc50fde78bf289f41d5f Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Wed, 9 Feb 2022 13:47:12 -0500 Subject: [PATCH] Introduce get_viewname() as a standard utility --- netbox/netbox/tables/columns.py | 5 ++--- netbox/utilities/templatetags/buttons.py | 22 ++++------------------ netbox/utilities/templatetags/helpers.py | 13 +++++-------- netbox/utilities/utils.py | 21 ++++++++++++++++----- 4 files changed, 27 insertions(+), 34 deletions(-) diff --git a/netbox/netbox/tables/columns.py b/netbox/netbox/tables/columns.py index fc28afe8d..284691469 100644 --- a/netbox/netbox/tables/columns.py +++ b/netbox/netbox/tables/columns.py @@ -10,7 +10,7 @@ from django.utils.safestring import mark_safe from django_tables2.utils import Accessor from extras.choices import CustomFieldTypeChoices -from utilities.utils import content_type_identifier, content_type_name, resolve_namespace +from utilities.utils import content_type_identifier, content_type_name, get_viewname __all__ = ( 'ActionsColumn', @@ -134,7 +134,6 @@ class ActionsColumn(tables.Column): return '' model = table.Meta.model - viewname_base = f'{resolve_namespace(model)}:{model._meta.model_name}' request = getattr(table, 'context', {}).get('request') url_appendix = f'?return_url={request.path}' if request else '' @@ -143,7 +142,7 @@ class ActionsColumn(tables.Column): for action, attrs in self.actions.items(): permission = f'{model._meta.app_label}.{attrs.permission}_{model._meta.model_name}' if attrs.permission is None or user.has_perm(permission): - url = reverse(f'{viewname_base}_{action}', kwargs={'pk': record.pk}) + url = reverse(get_viewname(model, action), kwargs={'pk': record.pk}) links.append(f'
  • ' f' {attrs.title}
  • ') diff --git a/netbox/utilities/templatetags/buttons.py b/netbox/utilities/templatetags/buttons.py index d8b4987ba..4b8fd931f 100644 --- a/netbox/utilities/templatetags/buttons.py +++ b/netbox/utilities/templatetags/buttons.py @@ -2,32 +2,18 @@ from django import template from django.urls import reverse from extras.models import ExportTemplate -from utilities.utils import prepare_cloned_fields +from utilities.utils import get_viewname, prepare_cloned_fields register = template.Library() -def _get_viewname(instance, action): - """ - Return the appropriate viewname for adding, editing, or deleting an instance. - """ - - # Validate action - assert action in ('add', 'edit', 'delete') - viewname = "{}:{}_{}".format( - instance._meta.app_label, instance._meta.model_name, action - ) - - return viewname - - # # Instance buttons # @register.inclusion_tag('buttons/clone.html') def clone_button(instance): - url = reverse(_get_viewname(instance, 'add')) + url = reverse(get_viewname(instance, 'add')) # Populate cloned field values param_string = prepare_cloned_fields(instance).urlencode() @@ -41,7 +27,7 @@ def clone_button(instance): @register.inclusion_tag('buttons/edit.html') def edit_button(instance): - viewname = _get_viewname(instance, 'edit') + viewname = get_viewname(instance, 'edit') url = reverse(viewname, kwargs={'pk': instance.pk}) return { @@ -51,7 +37,7 @@ def edit_button(instance): @register.inclusion_tag('buttons/delete.html') def delete_button(instance): - viewname = _get_viewname(instance, 'delete') + viewname = get_viewname(instance, 'delete') url = reverse(viewname, kwargs={'pk': instance.pk}) return { diff --git a/netbox/utilities/templatetags/helpers.py b/netbox/utilities/templatetags/helpers.py index be7dc97d1..89c218b9b 100644 --- a/netbox/utilities/templatetags/helpers.py +++ b/netbox/utilities/templatetags/helpers.py @@ -16,10 +16,9 @@ from django.utils.safestring import mark_safe from markdown import markdown from netbox.config import get_config -from netbox.settings import PLUGINS from utilities.forms import get_selected_values, TableConfigForm from utilities.markdown import StrikethroughExtension -from utilities.utils import foreground_color, resolve_namespace +from utilities.utils import foreground_color, get_viewname register = template.Library() @@ -116,8 +115,7 @@ def viewname(model, action): """ Return the view name for the given model and action. Does not perform any validation. """ - namespace = resolve_namespace(model) - return f'{namespace}:{model._meta.model_name}_{action}' + return get_viewname(model, action) @register.filter() @@ -125,11 +123,10 @@ def validated_viewname(model, action): """ Return the view name for the given model and action if valid, or None if invalid. """ - namespace = resolve_namespace(model) - viewname = f'{namespace}:{model._meta.model_name}_{action}' + viewname = get_viewname(model, action) + + # Validate the view name try: - # Validate and return the view name. We don't return the actual URL yet because many of the templates - # are written to pass a name to {% url %}. reverse(viewname) return viewname except NoReverseMatch: diff --git a/netbox/utilities/utils.py b/netbox/utilities/utils.py index 885beab10..e56da1b99 100644 --- a/netbox/utilities/utils.py +++ b/netbox/utilities/utils.py @@ -17,13 +17,24 @@ from extras.utils import is_taggable from utilities.constants import HTTP_REQUEST_META_SAFE_COPY -def resolve_namespace(instance): +def get_viewname(model, action=None): """ - Get the appropriate namepsace for the app based on whether it is a Plugin or base application + Return the view name for the given model and action, if valid. + + :param model: The model or instance to which the view applies + :param action: A string indicating the desired action (if any); e.g. "add" or "list" """ - if isinstance(instance._meta.app_config, PluginConfig): - return f'plugins:{instance._meta.app_label}' - return f'{instance._meta.app_label}' + viewname = f'{model._meta.app_label}:{model._meta.model_name}' + + # Determine whether this is a plugin view and adjust the namespace appropriately + if isinstance(model._meta.app_config, PluginConfig): + viewname = f'plugins:{viewname}' + + # Append the action, if any + if action: + viewname = f'{viewname}_{action}' + + return viewname def csv_format(data):