Przeglądaj źródła

Refactor ObjectChildrenView

jeremystretch 3 lat temu
rodzic
commit
c5770392e3

+ 6 - 20
netbox/netbox/views/generic/bulk_views.py

@@ -24,6 +24,7 @@ from utilities.htmx import is_htmx
 from utilities.permissions import get_permission_for_model
 from utilities.views import GetReturnURLMixin
 from .base import BaseMultiObjectView
+from .mixins import TableMixin
 
 __all__ = (
     'BulkComponentCreateView',
@@ -36,9 +37,9 @@ __all__ = (
 )
 
 
-class ObjectListView(BaseMultiObjectView):
+class ObjectListView(BaseMultiObjectView, TableMixin):
     """
-    Display multiple objects, all of the same type, as a table.
+    Display multiple objects, all the same type, as a table.
 
     Attributes:
         filterset: A django-filter FilterSet that is applied to the queryset
@@ -61,20 +62,6 @@ class ObjectListView(BaseMultiObjectView):
     def get_required_permission(self):
         return get_permission_for_model(self.queryset.model, 'view')
 
-    def get_table(self, request, bulk_actions=True):
-        """
-        Return the django-tables2 Table instance to be used for rendering the objects list.
-
-        Args:
-            request: The current request
-            bulk_actions: Show checkboxes for object selection
-        """
-        table = self.table(self.queryset, user=request.user)
-        if 'pk' in table.base_columns and bulk_actions:
-            table.columns.show('pk')
-
-        return table
-
     #
     # Export methods
     #
@@ -159,7 +146,7 @@ class ObjectListView(BaseMultiObjectView):
 
             # Export the current table view
             if request.GET['export'] == 'table':
-                table = self.get_table(request, has_bulk_actions)
+                table = self.get_table(self.queryset, request, has_bulk_actions)
                 columns = [name for name, _ in table.selected_columns]
                 return self.export_table(table, columns)
 
@@ -177,12 +164,11 @@ class ObjectListView(BaseMultiObjectView):
 
             # Fall back to default table/YAML export
             else:
-                table = self.get_table(request, has_bulk_actions)
+                table = self.get_table(self.queryset, request, has_bulk_actions)
                 return self.export_table(table)
 
         # Render the objects table
-        table = self.get_table(request, has_bulk_actions)
-        table.configure(request)
+        table = self.get_table(self.queryset, request, has_bulk_actions)
 
         # If this is an HTMX request, return only the rendered table HTML
         if is_htmx(request):

+ 22 - 0
netbox/netbox/views/generic/mixins.py

@@ -0,0 +1,22 @@
+__all__ = (
+    'TableMixin',
+)
+
+
+class TableMixin:
+
+    def get_table(self, data, request, bulk_actions=True):
+        """
+        Return the django-tables2 Table instance to be used for rendering the objects list.
+
+        Args:
+            data: Queryset or iterable containing table data
+            request: The current request
+            bulk_actions: Render checkboxes for object selection
+        """
+        table = self.table(data, user=request.user)
+        if 'pk' in table.base_columns and bulk_actions:
+            table.columns.show('pk')
+        table.configure(request)
+
+        return table

+ 25 - 14
netbox/netbox/views/generic/object_views.py

@@ -1,4 +1,5 @@
 import logging
+from collections import defaultdict
 from copy import deepcopy
 
 from django.contrib import messages
@@ -20,6 +21,7 @@ from utilities.permissions import get_permission_for_model
 from utilities.utils import get_viewname, normalize_querydict, prepare_cloned_fields
 from utilities.views import GetReturnURLMixin
 from .base import BaseObjectView
+from .mixins import TableMixin
 
 __all__ = (
     'ComponentCreateView',
@@ -69,23 +71,31 @@ class ObjectView(BaseObjectView):
         })
 
 
-class ObjectChildrenView(ObjectView):
+class ObjectChildrenView(ObjectView, TableMixin):
     """
     Display a table of child objects associated with the parent object.
 
     Attributes:
-        table: Table class used to render child objects list
+        child_model: The model class which represents the child objects
+        table: The django-tables2 Table class used to render the child objects list
+        filterset: A django-filter FilterSet that is applied to the queryset
     """
     child_model = None
     table = None
     filterset = None
+    actions = ('bulk_edit', 'bulk_delete')
+    action_perms = defaultdict(set, **{
+        'bulk_edit': {'change'},
+        'bulk_delete': {'delete'},
+    })
 
     def get_children(self, request, parent):
         """
         Return a QuerySet of child objects.
 
-        request: The current request
-        parent: The parent object
+        Args:
+            request: The current request
+            parent: The parent object
         """
         raise NotImplementedError(f'{self.__class__.__name__} must implement get_children()')
 
@@ -114,16 +124,16 @@ class ObjectChildrenView(ObjectView):
         if self.filterset:
             child_objects = self.filterset(request.GET, child_objects).qs
 
-        permissions = {}
-        for action in ('change', 'delete'):
-            perm_name = get_permission_for_model(self.child_model, action)
-            permissions[action] = request.user.has_perm(perm_name)
+        # Determine the available actions
+        actions = []
+        for action in self.actions:
+            if request.user.has_perms([
+                get_permission_for_model(self.child_model, name) for name in self.action_perms[action]
+            ]):
+                actions.append(action)
 
-        table = self.table(self.prep_table_data(request, child_objects, instance), user=request.user)
-        # Determine whether to display bulk action checkboxes
-        if 'pk' in table.base_columns and (permissions['change'] or permissions['delete']):
-            table.columns.show('pk')
-        table.configure(request)
+        table_data = self.prep_table_data(request, child_objects, instance)
+        table = self.get_table(table_data, request, bool(actions))
 
         # If this is an HTMX request, return only the rendered table HTML
         if is_htmx(request):
@@ -134,8 +144,9 @@ class ObjectChildrenView(ObjectView):
 
         return render(request, self.get_template_name(), {
             'object': instance,
+            'child_model': self.child_model,
             'table': table,
-            'permissions': permissions,
+            'actions': actions,
             **self.get_extra_context(request, instance),
         })