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

Move get_extra_context() to base views

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

+ 14 - 8
docs/plugins/development/generic-views.md

@@ -12,6 +12,9 @@ NetBox provides several generic view classes to facilitate common operations, su
 | `BulkEditView` | Edit multiple objects |
 | `BulkEditView` | Edit multiple objects |
 | `BulkDeleteView` | Delete multiple objects |
 | `BulkDeleteView` | Delete multiple objects |
 
 
+!!! note
+    Please note that only the classes which appear in this documentation are currently supported. Although other classes may be present within the `views.generic` module, they are not yet supported for use by plugins.
+
 ### Example Usage
 ### Example Usage
 
 
 ```python
 ```python
@@ -25,23 +28,19 @@ class ThingEditView(ObjectEditView):
     ...
     ...
 ```
 ```
 
 
-## Generic Views Reference
+## Object Views
 
 
-Below is the class definition for NetBox's base GenericView. The attributes and methods defined here are available on all generic views.
+Below is the class definition for NetBox's BaseObjectView. The attributes and methods defined here are available on all generic views which handle a single object.
 
 
-::: netbox.views.generic.base.GenericView
+::: netbox.views.generic.base.BaseObjectView
     rendering:
     rendering:
       show_source: false
       show_source: false
 
 
-!!! note
-    Please note that only the classes which appear in this documentation are currently supported. Although other classes may be present within the `views.generic` module, they are not yet supported for use by plugins.
-
 ::: netbox.views.generic.ObjectView
 ::: netbox.views.generic.ObjectView
     selection:
     selection:
       members:
       members:
         - get_object
         - get_object
         - get_template_name
         - get_template_name
-        - get_extra_context
     rendering:
     rendering:
       show_source: false
       show_source: false
 
 
@@ -60,11 +59,18 @@ Below is the class definition for NetBox's base GenericView. The attributes and
     rendering:
     rendering:
       show_source: false
       show_source: false
 
 
+## Multi-Object Views
+
+Below is the class definition for NetBox's BaseMultiObjectView. The attributes and methods defined here are available on all generic views which deal with multiple objects.
+
+::: netbox.views.generic.base.BaseMultiObjectView
+    rendering:
+      show_source: false
+
 ::: netbox.views.generic.ObjectListView
 ::: netbox.views.generic.ObjectListView
     selection:
     selection:
       members:
       members:
         - get_table
         - get_table
-        - get_extra_context
         - export_yaml
         - export_yaml
         - export_table
         - export_table
         - export_template
         - export_template

+ 32 - 1
netbox/netbox/views/generic/base.py

@@ -3,7 +3,7 @@ from django.views.generic import View
 from utilities.views import ObjectPermissionRequiredMixin
 from utilities.views import ObjectPermissionRequiredMixin
 
 
 
 
-class GenericView(ObjectPermissionRequiredMixin, View):
+class BaseObjectView(ObjectPermissionRequiredMixin, View):
     """
     """
     Base view class for reusable generic views.
     Base view class for reusable generic views.
 
 
@@ -13,3 +13,34 @@ class GenericView(ObjectPermissionRequiredMixin, View):
     """
     """
     queryset = None
     queryset = None
     template_name = None
     template_name = None
+
+    def get_extra_context(self, request, instance):
+        """
+        Return any additional context data to include when rendering the template.
+
+        Args:
+            request: The current request
+            instance: The object being viewed
+        """
+        return {}
+
+
+class BaseMultiObjectView(ObjectPermissionRequiredMixin, View):
+    """
+    Base view class for reusable generic views.
+
+    Attributes:
+        queryset: Django QuerySet from which the object(s) will be fetched
+        template_name: The name of the HTML template file to render
+    """
+    queryset = None
+    template_name = None
+
+    def get_extra_context(self, request):
+        """
+        Return any additional context data to include when rendering the template.
+
+        Args:
+            request: The current request
+        """
+        return {}

+ 27 - 30
netbox/netbox/views/generic/bulk_views.py

@@ -23,7 +23,7 @@ from utilities.htmx import is_htmx
 from utilities.permissions import get_permission_for_model
 from utilities.permissions import get_permission_for_model
 from utilities.tables import configure_table
 from utilities.tables import configure_table
 from utilities.views import GetReturnURLMixin
 from utilities.views import GetReturnURLMixin
-from .base import GenericView
+from .base import BaseMultiObjectView
 
 
 __all__ = (
 __all__ = (
     'BulkComponentCreateView',
     'BulkComponentCreateView',
@@ -36,7 +36,7 @@ __all__ = (
 )
 )
 
 
 
 
-class ObjectListView(GenericView):
+class ObjectListView(BaseMultiObjectView):
     """
     """
     Display multiple objects, all of the same type, as a table.
     Display multiple objects, all of the same type, as a table.
 
 
@@ -70,15 +70,6 @@ class ObjectListView(GenericView):
 
 
         return table
         return table
 
 
-    def get_extra_context(self, request):
-        """
-        Return any additional context data for the template.
-
-        Agrs:
-            request: The current request
-        """
-        return {}
-
     def get(self, request):
     def get(self, request):
         """
         """
         GET request handler.
         GET request handler.
@@ -139,8 +130,8 @@ class ObjectListView(GenericView):
             'permissions': permissions,
             'permissions': permissions,
             'action_buttons': self.action_buttons,
             'action_buttons': self.action_buttons,
             'filter_form': self.filterset_form(request.GET, label_suffix='') if self.filterset_form else None,
             'filter_form': self.filterset_form(request.GET, label_suffix='') if self.filterset_form else None,
+            **self.get_extra_context(request),
         }
         }
-        context.update(self.get_extra_context(request))
 
 
         return render(request, self.template_name, context)
         return render(request, self.template_name, context)
 
 
@@ -196,7 +187,7 @@ class ObjectListView(GenericView):
             return redirect(request.path)
             return redirect(request.path)
 
 
 
 
-class BulkCreateView(GetReturnURLMixin, GenericView):
+class BulkCreateView(GetReturnURLMixin, BaseMultiObjectView):
     """
     """
     Create new objects in bulk.
     Create new objects in bulk.
 
 
@@ -251,6 +242,7 @@ class BulkCreateView(GetReturnURLMixin, GenericView):
             'form': form,
             'form': form,
             'model_form': model_form,
             'model_form': model_form,
             'return_url': self.get_return_url(request),
             'return_url': self.get_return_url(request),
+            **self.get_extra_context(request),
         })
         })
 
 
     def post(self, request):
     def post(self, request):
@@ -295,10 +287,11 @@ class BulkCreateView(GetReturnURLMixin, GenericView):
             'model_form': model_form,
             'model_form': model_form,
             'obj_type': model._meta.verbose_name,
             'obj_type': model._meta.verbose_name,
             'return_url': self.get_return_url(request),
             'return_url': self.get_return_url(request),
+            **self.get_extra_context(request),
         })
         })
 
 
 
 
-class BulkImportView(GetReturnURLMixin, GenericView):
+class BulkImportView(GetReturnURLMixin, BaseMultiObjectView):
     """
     """
     Import objects in bulk (CSV format).
     Import objects in bulk (CSV format).
 
 
@@ -375,6 +368,7 @@ class BulkImportView(GetReturnURLMixin, GenericView):
             'fields': self.model_form().fields,
             'fields': self.model_form().fields,
             'obj_type': self.model_form._meta.model._meta.verbose_name,
             'obj_type': self.model_form._meta.model._meta.verbose_name,
             'return_url': self.get_return_url(request),
             'return_url': self.get_return_url(request),
+            **self.get_extra_context(request),
         })
         })
 
 
     def post(self, request):
     def post(self, request):
@@ -423,10 +417,11 @@ class BulkImportView(GetReturnURLMixin, GenericView):
             'fields': self.model_form().fields,
             'fields': self.model_form().fields,
             'obj_type': self.model_form._meta.model._meta.verbose_name,
             'obj_type': self.model_form._meta.model._meta.verbose_name,
             'return_url': self.get_return_url(request),
             'return_url': self.get_return_url(request),
+            **self.get_extra_context(request),
         })
         })
 
 
 
 
-class BulkEditView(GetReturnURLMixin, GenericView):
+class BulkEditView(GetReturnURLMixin, BaseMultiObjectView):
     """
     """
     Edit objects in bulk.
     Edit objects in bulk.
 
 
@@ -578,10 +573,11 @@ class BulkEditView(GetReturnURLMixin, GenericView):
             'table': table,
             'table': table,
             'obj_type_plural': model._meta.verbose_name_plural,
             'obj_type_plural': model._meta.verbose_name_plural,
             'return_url': self.get_return_url(request),
             'return_url': self.get_return_url(request),
+            **self.get_extra_context(request),
         })
         })
 
 
 
 
-class BulkRenameView(GetReturnURLMixin, GenericView):
+class BulkRenameView(GetReturnURLMixin, BaseMultiObjectView):
     """
     """
     An extendable view for renaming objects in bulk.
     An extendable view for renaming objects in bulk.
     """
     """
@@ -668,7 +664,7 @@ class BulkRenameView(GetReturnURLMixin, GenericView):
         })
         })
 
 
 
 
-class BulkDeleteView(GetReturnURLMixin, GenericView):
+class BulkDeleteView(GetReturnURLMixin, BaseMultiObjectView):
     """
     """
     Delete objects in bulk.
     Delete objects in bulk.
 
 
@@ -684,6 +680,18 @@ class BulkDeleteView(GetReturnURLMixin, GenericView):
     def get_required_permission(self):
     def get_required_permission(self):
         return get_permission_for_model(self.queryset.model, 'delete')
         return get_permission_for_model(self.queryset.model, 'delete')
 
 
+    def get_form(self):
+        """
+        Provide a standard bulk delete form if none has been specified for the view
+        """
+        class BulkDeleteForm(ConfirmationForm):
+            pk = ModelMultipleChoiceField(queryset=self.queryset, widget=MultipleHiddenInput)
+
+        if self.form:
+            return self.form
+
+        return BulkDeleteForm
+
     def get(self, request):
     def get(self, request):
         return redirect(self.get_return_url(request))
         return redirect(self.get_return_url(request))
 
 
@@ -746,26 +754,15 @@ class BulkDeleteView(GetReturnURLMixin, GenericView):
             'obj_type_plural': model._meta.verbose_name_plural,
             'obj_type_plural': model._meta.verbose_name_plural,
             'table': table,
             'table': table,
             'return_url': self.get_return_url(request),
             'return_url': self.get_return_url(request),
+            **self.get_extra_context(request),
         })
         })
 
 
-    def get_form(self):
-        """
-        Provide a standard bulk delete form if none has been specified for the view
-        """
-        class BulkDeleteForm(ConfirmationForm):
-            pk = ModelMultipleChoiceField(queryset=self.queryset, widget=MultipleHiddenInput)
-
-        if self.form:
-            return self.form
-
-        return BulkDeleteForm
-
 
 
 #
 #
 # Device/VirtualMachine components
 # Device/VirtualMachine components
 #
 #
 
 
-class BulkComponentCreateView(GetReturnURLMixin, GenericView):
+class BulkComponentCreateView(GetReturnURLMixin, BaseMultiObjectView):
     """
     """
     Add one or more components (e.g. interfaces, console ports, etc.) to a set of Devices or VirtualMachines.
     Add one or more components (e.g. interfaces, console ports, etc.) to a set of Devices or VirtualMachines.
     """
     """

+ 11 - 17
netbox/netbox/views/generic/object_views.py

@@ -21,7 +21,7 @@ from utilities.permissions import get_permission_for_model
 from utilities.tables import configure_table
 from utilities.tables import configure_table
 from utilities.utils import normalize_querydict, prepare_cloned_fields
 from utilities.utils import normalize_querydict, prepare_cloned_fields
 from utilities.views import GetReturnURLMixin
 from utilities.views import GetReturnURLMixin
-from .base import GenericView
+from .base import BaseObjectView
 
 
 __all__ = (
 __all__ = (
     'ComponentCreateView',
     'ComponentCreateView',
@@ -33,13 +33,12 @@ __all__ = (
 )
 )
 
 
 
 
-class ObjectView(GenericView):
+class ObjectView(BaseObjectView):
     """
     """
     Retrieve a single object for display.
     Retrieve a single object for display.
 
 
     Note: If `template_name` is not specified, it will be determined automatically based on the queryset model.
     Note: If `template_name` is not specified, it will be determined automatically based on the queryset model.
     """
     """
-
     def get_required_permission(self):
     def get_required_permission(self):
         return get_permission_for_model(self.queryset.model, 'view')
         return get_permission_for_model(self.queryset.model, 'view')
 
 
@@ -60,16 +59,6 @@ class ObjectView(GenericView):
         model_opts = self.queryset.model._meta
         model_opts = self.queryset.model._meta
         return f'{model_opts.app_label}/{model_opts.model_name}.html'
         return f'{model_opts.app_label}/{model_opts.model_name}.html'
 
 
-    def get_extra_context(self, request, instance):
-        """
-        Return any additional context data for the template.
-
-        Args:
-            request: The current request
-            instance: The object being viewed
-        """
-        return {}
-
     def get(self, request, **kwargs):
     def get(self, request, **kwargs):
         """
         """
         GET request handler. `*args` and `**kwargs` are passed to identify the object being queried.
         GET request handler. `*args` and `**kwargs` are passed to identify the object being queried.
@@ -152,7 +141,7 @@ class ObjectChildrenView(ObjectView):
         })
         })
 
 
 
 
-class ObjectImportView(GetReturnURLMixin, GenericView):
+class ObjectImportView(GetReturnURLMixin, BaseObjectView):
     """
     """
     Import a single object (YAML or JSON format).
     Import a single object (YAML or JSON format).
 
 
@@ -291,7 +280,7 @@ class ObjectImportView(GetReturnURLMixin, GenericView):
         })
         })
 
 
 
 
-class ObjectEditView(GetReturnURLMixin, GenericView):
+class ObjectEditView(GetReturnURLMixin, BaseObjectView):
     """
     """
     Create or edit a single object.
     Create or edit a single object.
 
 
@@ -362,6 +351,7 @@ class ObjectEditView(GetReturnURLMixin, GenericView):
             'obj_type': self.queryset.model._meta.verbose_name,
             'obj_type': self.queryset.model._meta.verbose_name,
             'form': form,
             'form': form,
             'return_url': self.get_return_url(request, obj),
             'return_url': self.get_return_url(request, obj),
+            **self.get_extra_context(request, obj),
         })
         })
 
 
     def post(self, request, *args, **kwargs):
     def post(self, request, *args, **kwargs):
@@ -435,10 +425,11 @@ class ObjectEditView(GetReturnURLMixin, GenericView):
             'obj_type': self.queryset.model._meta.verbose_name,
             'obj_type': self.queryset.model._meta.verbose_name,
             'form': form,
             'form': form,
             'return_url': self.get_return_url(request, obj),
             'return_url': self.get_return_url(request, obj),
+            **self.get_extra_context(request, obj),
         })
         })
 
 
 
 
-class ObjectDeleteView(GetReturnURLMixin, GenericView):
+class ObjectDeleteView(GetReturnURLMixin, BaseObjectView):
     """
     """
     Delete a single object.
     Delete a single object.
     """
     """
@@ -481,6 +472,7 @@ class ObjectDeleteView(GetReturnURLMixin, GenericView):
                 'object_type': self.queryset.model._meta.verbose_name,
                 'object_type': self.queryset.model._meta.verbose_name,
                 'form': form,
                 'form': form,
                 'form_url': form_url,
                 'form_url': form_url,
+                **self.get_extra_context(request, obj),
             })
             })
 
 
         return render(request, self.template_name, {
         return render(request, self.template_name, {
@@ -488,6 +480,7 @@ class ObjectDeleteView(GetReturnURLMixin, GenericView):
             'object_type': self.queryset.model._meta.verbose_name,
             'object_type': self.queryset.model._meta.verbose_name,
             'form': form,
             'form': form,
             'return_url': self.get_return_url(request, obj),
             'return_url': self.get_return_url(request, obj),
+            **self.get_extra_context(request, obj),
         })
         })
 
 
     def post(self, request, *args, **kwargs):
     def post(self, request, *args, **kwargs):
@@ -529,6 +522,7 @@ class ObjectDeleteView(GetReturnURLMixin, GenericView):
             'object_type': self.queryset.model._meta.verbose_name,
             'object_type': self.queryset.model._meta.verbose_name,
             'form': form,
             'form': form,
             'return_url': self.get_return_url(request, obj),
             'return_url': self.get_return_url(request, obj),
+            **self.get_extra_context(request, obj),
         })
         })
 
 
 
 
@@ -536,7 +530,7 @@ class ObjectDeleteView(GetReturnURLMixin, GenericView):
 # Device/VirtualMachine components
 # Device/VirtualMachine components
 #
 #
 
 
-class ComponentCreateView(GetReturnURLMixin, GenericView):
+class ComponentCreateView(GetReturnURLMixin, BaseObjectView):
     """
     """
     Add one or more components (e.g. interfaces, console ports, etc.) to a Device or VirtualMachine.
     Add one or more components (e.g. interfaces, console ports, etc.) to a Device or VirtualMachine.
     """
     """