Explorar o código

Merge pull request #8473 from netbox-community/6221-pluginviews

Closes #8472: Make view name resolution plugin-safe
Jeremy Stretch %!s(int64=4) %!d(string=hai) anos
pai
achega
3a447d5515

+ 2 - 2
netbox/netbox/tables/columns.py

@@ -10,7 +10,7 @@ from django.utils.safestring import mark_safe
 from django_tables2.utils import Accessor
 from django_tables2.utils import Accessor
 
 
 from extras.choices import CustomFieldTypeChoices
 from extras.choices import CustomFieldTypeChoices
-from utilities.utils import content_type_identifier, content_type_name
+from utilities.utils import content_type_identifier, content_type_name, resolve_namespace
 
 
 __all__ = (
 __all__ = (
     'ActionsColumn',
     'ActionsColumn',
@@ -134,7 +134,7 @@ class ActionsColumn(tables.Column):
             return ''
             return ''
 
 
         model = table.Meta.model
         model = table.Meta.model
-        viewname_base = f'{model._meta.app_label}:{model._meta.model_name}'
+        viewname_base = f'{resolve_namespace(model)}:{model._meta.model_name}'
         request = getattr(table, 'context', {}).get('request')
         request = getattr(table, 'context', {}).get('request')
         url_appendix = f'?return_url={request.path}' if request else ''
         url_appendix = f'?return_url={request.path}' if request else ''
 
 

+ 6 - 3
netbox/utilities/templatetags/helpers.py

@@ -16,9 +16,10 @@ from django.utils.safestring import mark_safe
 from markdown import markdown
 from markdown import markdown
 
 
 from netbox.config import get_config
 from netbox.config import get_config
+from netbox.settings import PLUGINS
 from utilities.forms import get_selected_values, TableConfigForm
 from utilities.forms import get_selected_values, TableConfigForm
 from utilities.markdown import StrikethroughExtension
 from utilities.markdown import StrikethroughExtension
-from utilities.utils import foreground_color
+from utilities.utils import foreground_color, resolve_namespace
 
 
 register = template.Library()
 register = template.Library()
 
 
@@ -115,7 +116,8 @@ def viewname(model, action):
     """
     """
     Return the view name for the given model and action. Does not perform any validation.
     Return the view name for the given model and action. Does not perform any validation.
     """
     """
-    return f'{model._meta.app_label}:{model._meta.model_name}_{action}'
+    namespace = resolve_namespace(model)
+    return f'{namespace}:{model._meta.model_name}_{action}'
 
 
 
 
 @register.filter()
 @register.filter()
@@ -123,7 +125,8 @@ def validated_viewname(model, action):
     """
     """
     Return the view name for the given model and action if valid, or None if invalid.
     Return the view name for the given model and action if valid, or None if invalid.
     """
     """
-    viewname = f'{model._meta.app_label}:{model._meta.model_name}_{action}'
+    namespace = resolve_namespace(model)
+    viewname = f'{namespace}:{model._meta.model_name}_{action}'
     try:
     try:
         # Validate and return the view name. We don't return the actual URL yet because many of the templates
         # 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 %}.
         # are written to pass a name to {% url %}.

+ 10 - 0
netbox/utilities/utils.py

@@ -13,10 +13,20 @@ from jinja2.sandbox import SandboxedEnvironment
 from mptt.models import MPTTModel
 from mptt.models import MPTTModel
 
 
 from dcim.choices import CableLengthUnitChoices
 from dcim.choices import CableLengthUnitChoices
+from extras.plugins import PluginConfig
 from extras.utils import is_taggable
 from extras.utils import is_taggable
 from utilities.constants import HTTP_REQUEST_META_SAFE_COPY
 from utilities.constants import HTTP_REQUEST_META_SAFE_COPY
 
 
 
 
+def resolve_namespace(instance):
+    """
+    Get the appropriate namepsace for the app based on whether it is a Plugin or base application
+    """
+    if isinstance(instance._meta.app_config, PluginConfig):
+        return f'plugins:{instance._meta.app_label}'
+    return f'{instance._meta.app_label}'
+
+
 def csv_format(data):
 def csv_format(data):
     """
     """
     Encapsulate any data which contains a comma within double quotes.
     Encapsulate any data which contains a comma within double quotes.