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 model_form = forms.CircuitTerminationForm
template_name = 'circuits/circuittermination_edit.html' 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: if 'circuit' in url_kwargs:
obj.circuit = get_object_or_404(Circuit, pk=url_kwargs['circuit']) obj.circuit = get_object_or_404(Circuit, pk=url_kwargs['circuit'])
return obj return obj

View File

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

View File

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

View File

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

View File

@ -55,14 +55,16 @@ class ObjectView(ObjectPermissionRequiredMixin, View):
""" """
Return any additional context data for the template. Return any additional context data for the template.
request: The current request :param request: The current request
instance: The object being viewed :param instance: The object being viewed
""" """
return {} return {}
def get(self, request, *args, **kwargs): 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) 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 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. table will prefetch objects as needed depending on the columns being displayed.
filter: A django-filter FilterSet that is applied to the queryset filterset: A django-filter FilterSet that is applied to the queryset
filter_form: The form used to render filter options filterset_form: The form used to render filter options
table: The django-tables2 Table used to render the objects list table: The django-tables2 Table used to render the objects list
template_name: The name of the template template_name: The name of the template
action_buttons: A list of buttons to include at the top of the page
""" """
queryset = None queryset = None
filterset = None filterset = None
@ -94,6 +97,13 @@ class ObjectListView(ObjectPermissionRequiredMixin, View):
return get_permission_for_model(self.queryset.model, 'view') return get_permission_for_model(self.queryset.model, 'view')
def get_table(self, request, permissions): 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) table = self.table(self.queryset, user=request.user)
if 'pk' in table.base_columns and (permissions['change'] or permissions['delete']): if 'pk' in table.base_columns and (permissions['change'] or permissions['delete']):
table.columns.show('pk') 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}") messages.error(request, f"There was an error rendering the selected export template ({template.name}): {e}")
return redirect(request.path) 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): def get(self, request):
"""
GET request handler.
:param request: The current request
"""
model = self.queryset.model model = self.queryset.model
content_type = ContentType.objects.get_for_model(model) content_type = ContentType.objects.get_for_model(model)
@ -192,19 +215,16 @@ class ObjectListView(ObjectPermissionRequiredMixin, View):
'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,
} }
context.update(self.extra_context()) context.update(self.get_extra_context(request))
return render(request, self.template_name, context) return render(request, self.template_name, context)
def extra_context(self):
return {}
class ObjectEditView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View): class ObjectEditView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View):
""" """
Create or edit a single object. 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 model_form: The form used to create or edit the object
template_name: The name of the template 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. # we are modifying an existing object or creating a new one.
return get_permission_for_model(self.queryset.model, self._permission_action) return get_permission_for_model(self.queryset.model, self._permission_action)
def get_object(self, kwargs): def get_object(self, **kwargs):
# Look up an existing object by slug or PK, if provided. """
if 'slug' in kwargs: Return an instance for editing. If a PK has been specified, this will be an existing object.
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()
:param kwargs: URL path kwargs
"""
if 'pk' in kwargs:
obj = get_object_or_404(self.queryset, **kwargs)
# Take a snapshot of change-logged models # Take a snapshot of change-logged models
if hasattr(obj, 'snapshot'): if hasattr(obj, 'snapshot'):
obj.snapshot() obj.snapshot()
return obj return obj
def alter_obj(self, obj, request, url_args, url_kwargs): return self.queryset.model()
# 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. 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 return obj
def dispatch(self, request, *args, **kwargs): def dispatch(self, request, *args, **kwargs):
@ -245,7 +271,13 @@ class ObjectEditView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View):
return super().dispatch(request, *args, **kwargs) return super().dispatch(request, *args, **kwargs)
def get(self, 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) initial_data = normalize_querydict(request.GET)
form = self.model_form(instance=obj, initial=initial_data) form = self.model_form(instance=obj, initial=initial_data)
@ -259,8 +291,15 @@ class ObjectEditView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View):
}) })
def post(self, request, *args, **kwargs): def post(self, request, *args, **kwargs):
"""
POST request handler.
:param request: The current request
"""
logger = logging.getLogger('netbox.views.ObjectEditView') 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( form = self.model_form(
data=request.POST, data=request.POST,
files=request.FILES, files=request.FILES,
@ -334,12 +373,13 @@ class ObjectDeleteView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View):
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_object(self, kwargs): def get_object(self, **kwargs):
# Look up object by slug if one has been provided. Otherwise, use PK. """
if 'slug' in kwargs: Return an instance for deletion. If a PK has been specified, this will be an existing object.
obj = get_object_or_404(self.queryset, slug=kwargs['slug'])
else: :param kwargs: URL path kwargs
obj = get_object_or_404(self.queryset, pk=kwargs['pk']) """
obj = get_object_or_404(self.queryset, **kwargs)
# Take a snapshot of change-logged models # Take a snapshot of change-logged models
if hasattr(obj, 'snapshot'): if hasattr(obj, 'snapshot'):
@ -347,8 +387,13 @@ class ObjectDeleteView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View):
return obj return obj
def get(self, request, **kwargs): def get(self, request, *args, **kwargs):
obj = self.get_object(kwargs) """
GET request handler.
:param request: The current request
"""
obj = self.get_object(**kwargs)
form = ConfirmationForm(initial=request.GET) form = ConfirmationForm(initial=request.GET)
return render(request, self.template_name, { return render(request, self.template_name, {
@ -358,9 +403,14 @@ class ObjectDeleteView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View):
'return_url': self.get_return_url(request, obj), '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') logger = logging.getLogger('netbox.views.ObjectDeleteView')
obj = self.get_object(kwargs) obj = self.get_object(**kwargs)
form = ConfirmationForm(request.POST) form = ConfirmationForm(request.POST)
if form.is_valid(): if form.is_valid():

View File

@ -353,7 +353,7 @@ class ContactAssignmentEditView(generic.ObjectEditView):
model_form = forms.ContactAssignmentForm model_form = forms.ContactAssignmentForm
template_name = 'tenancy/contactassignment_edit.html' 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: if not instance.pk:
# Assign the object based on URL kwargs # Assign the object based on URL kwargs
content_type = get_object_or_404(ContentType, pk=request.GET.get('content_type')) content_type = get_object_or_404(ContentType, pk=request.GET.get('content_type'))