1
0
mirror of https://github.com/netbox-community/netbox.git synced 2024-05-10 07:54:54 +00:00

Generic view cleanup

This commit is contained in:
jeremystretch
2021-12-14 11:28:13 -05:00
parent f2f6edabf9
commit 2dad35186a
6 changed files with 102 additions and 51 deletions

View File

@ -320,7 +320,7 @@ class CircuitTerminationEditView(generic.ObjectEditView):
model_form = forms.CircuitTerminationForm
template_name = 'circuits/circuittermination_edit.html'
def alter_obj(self, obj, request, url_args, url_kwargs):
def alter_object(self, obj, request, url_args, url_kwargs):
if 'circuit' in url_kwargs:
obj.circuit = get_object_or_404(Circuit, pk=url_kwargs['circuit'])
return obj

View File

@ -671,7 +671,7 @@ class RackReservationEditView(generic.ObjectEditView):
queryset = RackReservation.objects.all()
model_form = forms.RackReservationForm
def alter_obj(self, obj, request, args, kwargs):
def alter_object(self, obj, request, args, kwargs):
if not obj.pk:
if 'rack' in request.GET:
obj.rack = get_object_or_404(Rack, pk=request.GET.get('rack'))
@ -2342,7 +2342,7 @@ class CableCreateView(generic.ObjectEditView):
return super().dispatch(request, *args, **kwargs)
def alter_obj(self, obj, request, url_args, url_kwargs):
def alter_object(self, obj, request, url_args, url_kwargs):
termination_a_type = url_kwargs.get('termination_a_type')
termination_a_id = url_kwargs.get('termination_a_id')
termination_b_type_name = url_kwargs.get('termination_b_type')
@ -2355,7 +2355,8 @@ class CableCreateView(generic.ObjectEditView):
return obj
def get(self, request, *args, **kwargs):
obj = self.alter_obj(self.get_object(kwargs), request, args, kwargs)
obj = self.get_object(**kwargs)
obj = self.alter_object(obj, request, args, kwargs)
# Parse initial data manually to avoid setting field values as lists
initial_data = {k: request.GET[k] for k in request.GET}
@ -2423,7 +2424,7 @@ class ConsoleConnectionsListView(generic.ObjectListView):
template_name = 'dcim/connections_list.html'
action_buttons = ('export',)
def extra_context(self):
def get_extra_context(self, request):
return {
'title': 'Console Connections'
}
@ -2437,7 +2438,7 @@ class PowerConnectionsListView(generic.ObjectListView):
template_name = 'dcim/connections_list.html'
action_buttons = ('export',)
def extra_context(self):
def get_extra_context(self, request):
return {
'title': 'Power Connections'
}
@ -2451,7 +2452,7 @@ class InterfaceConnectionsListView(generic.ObjectListView):
template_name = 'dcim/connections_list.html'
action_buttons = ('export',)
def extra_context(self):
def get_extra_context(self, request):
return {
'title': 'Interface Connections'
}

View File

@ -472,7 +472,7 @@ class ImageAttachmentEditView(generic.ObjectEditView):
queryset = ImageAttachment.objects.all()
model_form = forms.ImageAttachmentForm
def alter_obj(self, instance, request, args, kwargs):
def alter_object(self, instance, request, args, kwargs):
if not instance.pk:
# Assign the parent object based on URL kwargs
content_type = get_object_or_404(ContentType, pk=request.GET.get('content_type'))
@ -510,7 +510,7 @@ class JournalEntryEditView(generic.ObjectEditView):
queryset = JournalEntry.objects.all()
model_form = forms.JournalEntryForm
def alter_obj(self, obj, request, args, kwargs):
def alter_object(self, obj, request, args, kwargs):
if not obj.pk:
obj.created_by = request.user
return obj

View File

@ -721,7 +721,7 @@ class IPAddressEditView(generic.ObjectEditView):
model_form = forms.IPAddressForm
template_name = 'ipam/ipaddress_edit.html'
def alter_obj(self, obj, request, url_args, url_kwargs):
def alter_object(self, obj, request, url_args, url_kwargs):
if 'interface' in request.GET:
try:
@ -975,7 +975,7 @@ class FHRPGroupAssignmentEditView(generic.ObjectEditView):
model_form = forms.FHRPGroupAssignmentForm
template_name = 'ipam/fhrpgroupassignment_edit.html'
def alter_obj(self, instance, request, args, kwargs):
def alter_object(self, instance, request, args, kwargs):
if not instance.pk:
# Assign the interface based on URL kwargs
content_type = get_object_or_404(ContentType, pk=request.GET.get('interface_type'))
@ -1092,7 +1092,7 @@ class ServiceEditView(generic.ObjectEditView):
model_form = forms.ServiceForm
template_name = 'ipam/service_edit.html'
def alter_obj(self, obj, request, url_args, url_kwargs):
def alter_object(self, obj, request, url_args, url_kwargs):
if 'device' in url_kwargs:
obj.device = get_object_or_404(
Device.objects.restrict(request.user),

View File

@ -55,14 +55,16 @@ class ObjectView(ObjectPermissionRequiredMixin, View):
"""
Return any additional context data for the template.
request: The current request
instance: The object being viewed
:param request: The current request
:param instance: The object being viewed
"""
return {}
def get(self, request, *args, **kwargs):
"""
Generic GET handler for accessing an object by PK or slug
GET request handler. *args and **kwargs are passed to identify the object being queried.
:param request: The current request
"""
instance = get_object_or_404(self.queryset, **kwargs)
@ -78,10 +80,11 @@ class ObjectListView(ObjectPermissionRequiredMixin, View):
queryset: The queryset of objects to display. Note: Prefetching related objects is not necessary, as the
table will prefetch objects as needed depending on the columns being displayed.
filter: A django-filter FilterSet that is applied to the queryset
filter_form: The form used to render filter options
filterset: A django-filter FilterSet that is applied to the queryset
filterset_form: The form used to render filter options
table: The django-tables2 Table used to render the objects list
template_name: The name of the template
action_buttons: A list of buttons to include at the top of the page
"""
queryset = None
filterset = None
@ -94,6 +97,13 @@ class ObjectListView(ObjectPermissionRequiredMixin, View):
return get_permission_for_model(self.queryset.model, 'view')
def get_table(self, request, permissions):
"""
Return the django-tables2 Table instance to be used for rendering the objects list.
:param request: The current request
:param permissions: A dictionary mapping of the view, add, change, and delete permissions to booleans indicating
whether the user has each
"""
table = self.table(self.queryset, user=request.user)
if 'pk' in table.base_columns and (permissions['change'] or permissions['delete']):
table.columns.show('pk')
@ -143,7 +153,20 @@ class ObjectListView(ObjectPermissionRequiredMixin, View):
messages.error(request, f"There was an error rendering the selected export template ({template.name}): {e}")
return redirect(request.path)
def get_extra_context(self, request):
"""
Return any additional context data for the template.
:param request: The current request
"""
return {}
def get(self, request):
"""
GET request handler.
:param request: The current request
"""
model = self.queryset.model
content_type = ContentType.objects.get_for_model(model)
@ -192,19 +215,16 @@ class ObjectListView(ObjectPermissionRequiredMixin, View):
'action_buttons': self.action_buttons,
'filter_form': self.filterset_form(request.GET, label_suffix='') if self.filterset_form else None,
}
context.update(self.extra_context())
context.update(self.get_extra_context(request))
return render(request, self.template_name, context)
def extra_context(self):
return {}
class ObjectEditView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View):
"""
Create or edit a single object.
queryset: The base queryset for the object being modified
queryset: The base QuerySet for the object being modified
model_form: The form used to create or edit the object
template_name: The name of the template
"""
@ -217,25 +237,31 @@ class ObjectEditView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View):
# we are modifying an existing object or creating a new one.
return get_permission_for_model(self.queryset.model, self._permission_action)
def get_object(self, kwargs):
# Look up an existing object by slug or PK, if provided.
if 'slug' in kwargs:
obj = get_object_or_404(self.queryset, slug=kwargs['slug'])
elif 'pk' in kwargs:
obj = get_object_or_404(self.queryset, pk=kwargs['pk'])
# Otherwise, return a new instance.
else:
return self.queryset.model()
def get_object(self, **kwargs):
"""
Return an instance for editing. If a PK has been specified, this will be an existing object.
:param kwargs: URL path kwargs
"""
if 'pk' in kwargs:
obj = get_object_or_404(self.queryset, **kwargs)
# Take a snapshot of change-logged models
if hasattr(obj, 'snapshot'):
obj.snapshot()
return obj
def alter_obj(self, obj, request, url_args, url_kwargs):
# Allow views to add extra info to an object before it is processed. For example, a parent object can be defined
# given some parameter from the request URL.
return self.queryset.model()
def alter_object(self, obj, request, url_args, url_kwargs):
"""
Provides a hook for views to modify an object before it is processed. For example, a parent object can be
defined given some parameter from the request URL.
:param obj: The object being edited
:param request: The current request
:param url_args: URL path args
:param url_kwargs: URL path kwargs
"""
return obj
def dispatch(self, request, *args, **kwargs):
@ -245,7 +271,13 @@ class ObjectEditView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View):
return super().dispatch(request, *args, **kwargs)
def get(self, request, *args, **kwargs):
obj = self.alter_obj(self.get_object(kwargs), request, args, kwargs)
"""
GET request handler.
:param request: The current request
"""
obj = self.get_object(**kwargs)
obj = self.alter_object(obj, request, args, kwargs)
initial_data = normalize_querydict(request.GET)
form = self.model_form(instance=obj, initial=initial_data)
@ -259,8 +291,15 @@ class ObjectEditView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View):
})
def post(self, request, *args, **kwargs):
"""
POST request handler.
:param request: The current request
"""
logger = logging.getLogger('netbox.views.ObjectEditView')
obj = self.alter_obj(self.get_object(kwargs), request, args, kwargs)
obj = self.get_object(**kwargs)
obj = self.alter_object(obj, request, args, kwargs)
form = self.model_form(
data=request.POST,
files=request.FILES,
@ -334,12 +373,13 @@ class ObjectDeleteView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View):
def get_required_permission(self):
return get_permission_for_model(self.queryset.model, 'delete')
def get_object(self, kwargs):
# Look up object by slug if one has been provided. Otherwise, use PK.
if 'slug' in kwargs:
obj = get_object_or_404(self.queryset, slug=kwargs['slug'])
else:
obj = get_object_or_404(self.queryset, pk=kwargs['pk'])
def get_object(self, **kwargs):
"""
Return an instance for deletion. If a PK has been specified, this will be an existing object.
:param kwargs: URL path kwargs
"""
obj = get_object_or_404(self.queryset, **kwargs)
# Take a snapshot of change-logged models
if hasattr(obj, 'snapshot'):
@ -347,8 +387,13 @@ class ObjectDeleteView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View):
return obj
def get(self, request, **kwargs):
obj = self.get_object(kwargs)
def get(self, request, *args, **kwargs):
"""
GET request handler.
:param request: The current request
"""
obj = self.get_object(**kwargs)
form = ConfirmationForm(initial=request.GET)
return render(request, self.template_name, {
@ -358,9 +403,14 @@ class ObjectDeleteView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View):
'return_url': self.get_return_url(request, obj),
})
def post(self, request, **kwargs):
def post(self, request, *args, **kwargs):
"""
POST request handler.
:param request: The current request
"""
logger = logging.getLogger('netbox.views.ObjectDeleteView')
obj = self.get_object(kwargs)
obj = self.get_object(**kwargs)
form = ConfirmationForm(request.POST)
if form.is_valid():

View File

@ -353,7 +353,7 @@ class ContactAssignmentEditView(generic.ObjectEditView):
model_form = forms.ContactAssignmentForm
template_name = 'tenancy/contactassignment_edit.html'
def alter_obj(self, instance, request, args, kwargs):
def alter_object(self, instance, request, args, kwargs):
if not instance.pk:
# Assign the object based on URL kwargs
content_type = get_object_or_404(ContentType, pk=request.GET.get('content_type'))