Просмотр исходного кода

Fixes #8764: Correct view name resolution for dynamic form fields

jeremystretch 4 лет назад
Родитель
Сommit
d6c272cfd6

+ 1 - 0
docs/release-notes/version-3.2.md

@@ -155,6 +155,7 @@ Where it is desired to limit the range of available VLANs within a group, users
 * [#8682](https://github.com/netbox-community/netbox/issues/8682) - Limit available VLANs by group min/max VIDs
 * [#8683](https://github.com/netbox-community/netbox/issues/8683) - Fix `ZoneInfoNotFoundError` exception under Python 3.9+
 * [#8761](https://github.com/netbox-community/netbox/issues/8761) - Correct view name resolution under journal entry views
+* [#8764](https://github.com/netbox-community/netbox/issues/8764) - Correct view name resolution for dynamic form fields
 
 ### Other Changes
 

+ 3 - 4
netbox/utilities/forms/fields/dynamic.py

@@ -5,6 +5,7 @@ from django.forms import BoundField
 from django.urls import reverse
 
 from utilities.forms import widgets
+from utilities.utils import get_viewname
 
 __all__ = (
     'DynamicModelChoiceField',
@@ -101,10 +102,8 @@ class DynamicModelChoiceMixin:
         # Set the data URL on the APISelect widget (if not already set)
         widget = bound_field.field.widget
         if not widget.attrs.get('data-url'):
-            app_label = self.queryset.model._meta.app_label
-            model_name = self.queryset.model._meta.model_name
-            data_url = reverse('{}-api:{}-list'.format(app_label, model_name))
-            widget.attrs['data-url'] = data_url
+            viewname = get_viewname(self.queryset.model, action='list', rest_api=True)
+            widget.attrs['data-url'] = reverse(viewname)
 
         return bound_field
 

+ 21 - 8
netbox/utilities/utils.py

@@ -17,22 +17,35 @@ from extras.utils import is_taggable
 from utilities.constants import HTTP_REQUEST_META_SAFE_COPY
 
 
-def get_viewname(model, action=None):
+def get_viewname(model, action=None, rest_api=False):
     """
     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"
+    :param rest_api: A boolean indicating whether this is a REST API view
     """
-    viewname = f'{model._meta.app_label}:{model._meta.model_name}'
+    is_plugin = isinstance(model._meta.app_config, PluginConfig)
+    app_label = model._meta.app_label
+    model_name = 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}'
+    if rest_api:
+        if is_plugin:
+            viewname = f'plugins-api:{app_label}:{model_name}'
+        else:
+            viewname = f'{app_label}-api:{model_name}'
+        # Append the action, if any
+        if action:
+            viewname = f'{viewname}-{action}'
 
-    # Append the action, if any
-    if action:
-        viewname = f'{viewname}_{action}'
+    else:
+        viewname = f'{app_label}:{model_name}'
+        # Prepend the plugins namespace if this is a plugin model
+        if is_plugin:
+            viewname = f'plugins:{viewname}'
+        # Append the action, if any
+        if action:
+            viewname = f'{viewname}_{action}'
 
     return viewname