diff --git a/netbox/dcim/views.py b/netbox/dcim/views.py index 8472102670d..63666cce0ed 100644 --- a/netbox/dcim/views.py +++ b/netbox/dcim/views.py @@ -4060,6 +4060,7 @@ class InventoryItemRoleListView(generic.ObjectListView): @register_model_view(InventoryItemRole) class InventoryItemRoleView(GetRelatedModelsMixin, generic.ObjectView): queryset = InventoryItemRole.objects.all() + template_name = 'generic/object.html' layout = layout.SimpleLayout( left_panels=[ panels.InventoryItemRolePanel(), @@ -4308,6 +4309,7 @@ class CableListView(generic.ObjectListView): @register_model_view(Cable) class CableView(generic.ObjectView): queryset = Cable.objects.all() + template_name = 'generic/object.html' layout = layout.SimpleLayout( left_panels=[ panels.CablePanel(), @@ -4458,6 +4460,7 @@ class VirtualChassisListView(generic.ObjectListView): @register_model_view(VirtualChassis) class VirtualChassisView(generic.ObjectView): queryset = VirtualChassis.objects.all() + template_name = 'generic/object.html' layout = layout.SimpleLayout( left_panels=[ panels.VirtualChassisPanel(), @@ -4883,6 +4886,7 @@ class VirtualDeviceContextListView(generic.ObjectListView): @register_model_view(VirtualDeviceContext) class VirtualDeviceContextView(GetRelatedModelsMixin, generic.ObjectView): queryset = VirtualDeviceContext.objects.all() + template_name = 'generic/object.html' layout = layout.SimpleLayout( left_panels=[ panels.VirtualDeviceContextPanel(), @@ -4968,6 +4972,7 @@ class MACAddressListView(generic.ObjectListView): @register_model_view(MACAddress) class MACAddressView(generic.ObjectView): queryset = MACAddress.objects.all() + template_name = 'generic/object.html' layout = layout.SimpleLayout( left_panels=[ panels.MACAddressPanel(), diff --git a/netbox/extras/views.py b/netbox/extras/views.py index bef085e0c23..829413637eb 100644 --- a/netbox/extras/views.py +++ b/netbox/extras/views.py @@ -65,6 +65,7 @@ class CustomFieldListView(generic.ObjectListView): @register_model_view(CustomField) class CustomFieldView(generic.ObjectView): queryset = CustomField.objects.select_related('choice_set') + template_name = 'generic/object.html' layout = layout.SimpleLayout( left_panels=[ panels.CustomFieldPanel(), @@ -148,6 +149,7 @@ class CustomFieldChoiceSetListView(generic.ObjectListView): @register_model_view(CustomFieldChoiceSet) class CustomFieldChoiceSetView(generic.ObjectView): queryset = CustomFieldChoiceSet.objects.all() + template_name = 'generic/object.html' layout = layout.SimpleLayout( left_panels=[ panels.CustomFieldChoiceSetPanel(), @@ -231,6 +233,7 @@ class CustomLinkListView(generic.ObjectListView): @register_model_view(CustomLink) class CustomLinkView(generic.ObjectView): queryset = CustomLink.objects.all() + template_name = 'generic/object.html' layout = layout.SimpleLayout( left_panels=[ panels.CustomLinkPanel(), @@ -298,6 +301,7 @@ class ExportTemplateListView(generic.ObjectListView): @register_model_view(ExportTemplate) class ExportTemplateView(generic.ObjectView): queryset = ExportTemplate.objects.all() + template_name = 'generic/object.html' layout = layout.SimpleLayout( left_panels=[ panels.ExportTemplatePanel(), @@ -372,6 +376,7 @@ class SavedFilterListView(SharedObjectViewMixin, generic.ObjectListView): @register_model_view(SavedFilter) class SavedFilterView(SharedObjectViewMixin, generic.ObjectView): queryset = SavedFilter.objects.all() + template_name = 'generic/object.html' layout = layout.SimpleLayout( left_panels=[ panels.SavedFilterPanel(), @@ -443,6 +448,7 @@ class TableConfigListView(SharedObjectViewMixin, generic.ObjectListView): @register_model_view(TableConfig) class TableConfigView(SharedObjectViewMixin, generic.ObjectView): queryset = TableConfig.objects.all() + template_name = 'generic/object.html' layout = layout.SimpleLayout( left_panels=[ panels.TableConfigPanel(), @@ -545,6 +551,7 @@ class NotificationGroupListView(generic.ObjectListView): @register_model_view(NotificationGroup) class NotificationGroupView(generic.ObjectView): queryset = NotificationGroup.objects.all() + template_name = 'generic/object.html' layout = layout.SimpleLayout( left_panels=[ panels.NotificationGroupPanel(), @@ -738,6 +745,7 @@ class WebhookListView(generic.ObjectListView): @register_model_view(Webhook) class WebhookView(generic.ObjectView): queryset = Webhook.objects.all() + template_name = 'generic/object.html' layout = layout.SimpleLayout( left_panels=[ panels.WebhookPanel(), @@ -807,6 +815,7 @@ class EventRuleListView(generic.ObjectListView): @register_model_view(EventRule) class EventRuleView(generic.ObjectView): queryset = EventRule.objects.all() + template_name = 'generic/object.html' layout = layout.SimpleLayout( left_panels=[ panels.EventRulePanel(), @@ -878,6 +887,7 @@ class TagListView(generic.ObjectListView): @register_model_view(Tag) class TagView(generic.ObjectView): queryset = Tag.objects.all() + template_name = 'generic/object.html' layout = layout.SimpleLayout( left_panels=[ panels.TagPanel(), @@ -969,6 +979,7 @@ class ConfigContextProfileListView(generic.ObjectListView): @register_model_view(ConfigContextProfile) class ConfigContextProfileView(generic.ObjectView): queryset = ConfigContextProfile.objects.all() + template_name = 'generic/object.html' layout = layout.SimpleLayout( left_panels=[ panels.ConfigContextProfilePanel(), @@ -1043,6 +1054,7 @@ class ConfigContextListView(generic.ObjectListView): @register_model_view(ConfigContext) class ConfigContextView(generic.ObjectView): queryset = ConfigContext.objects.all() + template_name = 'generic/object.html' layout = layout.SimpleLayout( left_panels=[ panels.ConfigContextPanel(), @@ -1172,6 +1184,7 @@ class ConfigTemplateListView(generic.ObjectListView): @register_model_view(ConfigTemplate) class ConfigTemplateView(generic.ObjectView): queryset = ConfigTemplate.objects.all() + template_name = 'generic/object.html' layout = layout.SimpleLayout( left_panels=[ panels.ConfigTemplatePanel(), @@ -1302,6 +1315,7 @@ class ImageAttachmentListView(generic.ObjectListView): @register_model_view(ImageAttachment) class ImageAttachmentView(generic.ObjectView): queryset = ImageAttachment.objects.all() + template_name = 'generic/object.html' layout = layout.SimpleLayout( left_panels=[ panels.ImageAttachmentPanel(), diff --git a/netbox/ipam/views.py b/netbox/ipam/views.py index 3b1ce9b10f4..1e9986fb9b3 100644 --- a/netbox/ipam/views.py +++ b/netbox/ipam/views.py @@ -51,6 +51,7 @@ class VRFListView(generic.ObjectListView): @register_model_view(VRF) class VRFView(GetRelatedModelsMixin, generic.ObjectView): queryset = VRF.objects.all() + template_name = 'generic/object.html' layout = layout.Layout( layout.Row( layout.Column( @@ -172,6 +173,7 @@ class RouteTargetListView(generic.ObjectListView): @register_model_view(RouteTarget) class RouteTargetView(generic.ObjectView): queryset = RouteTarget.objects.all() + template_name = 'generic/object.html' layout = layout.Layout( layout.Row( layout.Column( @@ -1332,6 +1334,7 @@ class VLANTranslationPolicyListView(generic.ObjectListView): @register_model_view(VLANTranslationPolicy) class VLANTranslationPolicyView(generic.ObjectView): queryset = VLANTranslationPolicy.objects.all() + template_name = 'generic/object.html' layout = layout.SimpleLayout( left_panels=[ panels.VLANTranslationPolicyPanel(), @@ -1414,6 +1417,7 @@ class VLANTranslationRuleListView(generic.ObjectListView): @register_model_view(VLANTranslationRule) class VLANTranslationRuleView(generic.ObjectView): queryset = VLANTranslationRule.objects.all() + template_name = 'generic/object.html' layout = layout.SimpleLayout( left_panels=[ panels.VLANTranslationRulePanel(), @@ -1753,6 +1757,7 @@ class ServiceTemplateListView(generic.ObjectListView): @register_model_view(ServiceTemplate) class ServiceTemplateView(generic.ObjectView): queryset = ServiceTemplate.objects.all() + template_name = 'generic/object.html' layout = layout.SimpleLayout( left_panels=[ panels.ServiceTemplatePanel(), diff --git a/netbox/netbox/views/generic/feature_views.py b/netbox/netbox/views/generic/feature_views.py index 8e07f8ad4da..a12e357cfde 100644 --- a/netbox/netbox/views/generic/feature_views.py +++ b/netbox/netbox/views/generic/feature_views.py @@ -17,7 +17,7 @@ from tenancy.models import ContactAssignment from tenancy.tables import ContactAssignmentTable from utilities.permissions import get_permission_for_model -from utilities.views import ConditionalLoginRequiredMixin, GetReturnURLMixin, ViewTab +from utilities.views import ConditionalLoginRequiredMixin, GetReturnURLMixin, ViewTab, get_default_template from .base import BaseMultiObjectView from .object_views import ObjectChildrenView @@ -72,15 +72,10 @@ def get(self, request, model, **kwargs): ) objectchanges_table.configure(request) - # Default to using "/.html" as the template, if it exists. Otherwise, - # fall back to using base.html. - if self.base_template is None: - self.base_template = f"{model._meta.app_label}/{model._meta.model_name}.html" - return render(request, 'extras/object_changelog.html', { 'object': obj, 'table': objectchanges_table, - 'base_template': self.base_template, + 'base_template': self.base_template or get_default_template(model), 'tab': self.tab, }) @@ -107,15 +102,10 @@ def get(self, request, model, **kwargs): object_id=obj.pk, ) - # Default to using "/.html" as the template, if it exists. Otherwise, - # fall back to using base.html. - if self.base_template is None: - self.base_template = f"{model._meta.app_label}/{model._meta.model_name}.html" - return render(request, 'extras/object_imageattachments.html', { 'object': obj, 'image_attachments': image_attachments, - 'base_template': self.base_template, + 'base_template': self.base_template or get_default_template(model), 'tab': self.tab, }) @@ -167,16 +157,11 @@ def get(self, request, model, **kwargs): else: form = None - # Default to using "/.html" as the template, if it exists. Otherwise, - # fall back to using base.html. - if self.base_template is None: - self.base_template = f"{model._meta.app_label}/{model._meta.model_name}.html" - return render(request, 'extras/object_journal.html', { 'object': obj, 'form': form, 'table': journalentry_table, - 'base_template': self.base_template, + 'base_template': self.base_template or get_default_template(model), 'tab': self.tab, }) @@ -222,15 +207,10 @@ def get(self, request, model, **kwargs): jobs_table = JobTable(data=jobs, orderable=False) jobs_table.configure(request) - # Default to using "/.html" as the template, if it exists. Otherwise, - # fall back to using base.html. - if self.base_template is None: - self.base_template = f"{model._meta.app_label}/{model._meta.model_name}.html" - return render(request, 'core/object_jobs.html', { 'object': obj, 'table': jobs_table, - 'base_template': self.base_template, + 'base_template': self.base_template or get_default_template(model), 'tab': self.tab, }) diff --git a/netbox/netbox/views/generic/object_views.py b/netbox/netbox/views/generic/object_views.py index c6630d34100..0d4db853904 100644 --- a/netbox/netbox/views/generic/object_views.py +++ b/netbox/netbox/views/generic/object_views.py @@ -22,7 +22,7 @@ from utilities.querydict import normalize_querydict, prepare_cloned_fields from utilities.request import safe_for_redirect from utilities.tables import get_table_configs -from utilities.views import GetReturnURLMixin, get_action_url +from utilities.views import GetReturnURLMixin, get_action_url, get_default_template from .base import BaseObjectView from .mixins import ActionsMixin, TableMixin @@ -163,7 +163,7 @@ def get(self, request, *args, **kwargs): 'object': instance, 'model': self.child_model, 'child_model': self.child_model, - 'base_template': f'{instance._meta.app_label}/{instance._meta.model_name}.html', + 'base_template': get_default_template(instance), 'table': table, 'table_config': f'{table.name}_config', 'table_configs': get_table_configs(table, request.user), diff --git a/netbox/templates/dcim/cable.html b/netbox/templates/dcim/cable.html deleted file mode 100644 index f15e1d0501e..00000000000 --- a/netbox/templates/dcim/cable.html +++ /dev/null @@ -1 +0,0 @@ -{% extends 'generic/object.html' %} diff --git a/netbox/templates/dcim/inventoryitemrole.html b/netbox/templates/dcim/inventoryitemrole.html deleted file mode 100644 index f15e1d0501e..00000000000 --- a/netbox/templates/dcim/inventoryitemrole.html +++ /dev/null @@ -1 +0,0 @@ -{% extends 'generic/object.html' %} diff --git a/netbox/templates/dcim/macaddress.html b/netbox/templates/dcim/macaddress.html deleted file mode 100644 index f15e1d0501e..00000000000 --- a/netbox/templates/dcim/macaddress.html +++ /dev/null @@ -1 +0,0 @@ -{% extends 'generic/object.html' %} diff --git a/netbox/templates/dcim/moduletypeprofile.html b/netbox/templates/dcim/moduletypeprofile.html deleted file mode 100644 index f15e1d0501e..00000000000 --- a/netbox/templates/dcim/moduletypeprofile.html +++ /dev/null @@ -1 +0,0 @@ -{% extends 'generic/object.html' %} diff --git a/netbox/templates/dcim/racktype.html b/netbox/templates/dcim/racktype.html deleted file mode 100644 index f15e1d0501e..00000000000 --- a/netbox/templates/dcim/racktype.html +++ /dev/null @@ -1 +0,0 @@ -{% extends 'generic/object.html' %} diff --git a/netbox/templates/dcim/virtualchassis.html b/netbox/templates/dcim/virtualchassis.html deleted file mode 100644 index f15e1d0501e..00000000000 --- a/netbox/templates/dcim/virtualchassis.html +++ /dev/null @@ -1 +0,0 @@ -{% extends 'generic/object.html' %} diff --git a/netbox/templates/dcim/virtualdevicecontext.html b/netbox/templates/dcim/virtualdevicecontext.html deleted file mode 100644 index f15e1d0501e..00000000000 --- a/netbox/templates/dcim/virtualdevicecontext.html +++ /dev/null @@ -1 +0,0 @@ -{% extends 'generic/object.html' %} diff --git a/netbox/templates/extras/configcontext.html b/netbox/templates/extras/configcontext.html deleted file mode 100644 index f15e1d0501e..00000000000 --- a/netbox/templates/extras/configcontext.html +++ /dev/null @@ -1 +0,0 @@ -{% extends 'generic/object.html' %} diff --git a/netbox/templates/extras/configcontextprofile.html b/netbox/templates/extras/configcontextprofile.html deleted file mode 100644 index f15e1d0501e..00000000000 --- a/netbox/templates/extras/configcontextprofile.html +++ /dev/null @@ -1 +0,0 @@ -{% extends 'generic/object.html' %} diff --git a/netbox/templates/extras/configtemplate.html b/netbox/templates/extras/configtemplate.html deleted file mode 100644 index f15e1d0501e..00000000000 --- a/netbox/templates/extras/configtemplate.html +++ /dev/null @@ -1 +0,0 @@ -{% extends 'generic/object.html' %} diff --git a/netbox/templates/extras/customfield.html b/netbox/templates/extras/customfield.html deleted file mode 100644 index f15e1d0501e..00000000000 --- a/netbox/templates/extras/customfield.html +++ /dev/null @@ -1 +0,0 @@ -{% extends 'generic/object.html' %} diff --git a/netbox/templates/extras/customfieldchoiceset.html b/netbox/templates/extras/customfieldchoiceset.html deleted file mode 100644 index f15e1d0501e..00000000000 --- a/netbox/templates/extras/customfieldchoiceset.html +++ /dev/null @@ -1 +0,0 @@ -{% extends 'generic/object.html' %} diff --git a/netbox/templates/extras/customlink.html b/netbox/templates/extras/customlink.html deleted file mode 100644 index f15e1d0501e..00000000000 --- a/netbox/templates/extras/customlink.html +++ /dev/null @@ -1 +0,0 @@ -{% extends 'generic/object.html' %} diff --git a/netbox/templates/extras/eventrule.html b/netbox/templates/extras/eventrule.html deleted file mode 100644 index f15e1d0501e..00000000000 --- a/netbox/templates/extras/eventrule.html +++ /dev/null @@ -1 +0,0 @@ -{% extends 'generic/object.html' %} diff --git a/netbox/templates/extras/exporttemplate.html b/netbox/templates/extras/exporttemplate.html deleted file mode 100644 index f15e1d0501e..00000000000 --- a/netbox/templates/extras/exporttemplate.html +++ /dev/null @@ -1 +0,0 @@ -{% extends 'generic/object.html' %} diff --git a/netbox/templates/extras/imageattachment.html b/netbox/templates/extras/imageattachment.html deleted file mode 100644 index f15e1d0501e..00000000000 --- a/netbox/templates/extras/imageattachment.html +++ /dev/null @@ -1 +0,0 @@ -{% extends 'generic/object.html' %} diff --git a/netbox/templates/extras/notificationgroup.html b/netbox/templates/extras/notificationgroup.html deleted file mode 100644 index f15e1d0501e..00000000000 --- a/netbox/templates/extras/notificationgroup.html +++ /dev/null @@ -1 +0,0 @@ -{% extends 'generic/object.html' %} diff --git a/netbox/templates/extras/savedfilter.html b/netbox/templates/extras/savedfilter.html deleted file mode 100644 index f15e1d0501e..00000000000 --- a/netbox/templates/extras/savedfilter.html +++ /dev/null @@ -1 +0,0 @@ -{% extends 'generic/object.html' %} diff --git a/netbox/templates/extras/tableconfig.html b/netbox/templates/extras/tableconfig.html deleted file mode 100644 index f15e1d0501e..00000000000 --- a/netbox/templates/extras/tableconfig.html +++ /dev/null @@ -1 +0,0 @@ -{% extends 'generic/object.html' %} diff --git a/netbox/templates/extras/tag.html b/netbox/templates/extras/tag.html deleted file mode 100644 index f15e1d0501e..00000000000 --- a/netbox/templates/extras/tag.html +++ /dev/null @@ -1 +0,0 @@ -{% extends 'generic/object.html' %} diff --git a/netbox/templates/extras/webhook.html b/netbox/templates/extras/webhook.html deleted file mode 100644 index f15e1d0501e..00000000000 --- a/netbox/templates/extras/webhook.html +++ /dev/null @@ -1 +0,0 @@ -{% extends 'generic/object.html' %} diff --git a/netbox/templates/ipam/routetarget.html b/netbox/templates/ipam/routetarget.html deleted file mode 100644 index f15e1d0501e..00000000000 --- a/netbox/templates/ipam/routetarget.html +++ /dev/null @@ -1 +0,0 @@ -{% extends 'generic/object.html' %} diff --git a/netbox/templates/ipam/servicetemplate.html b/netbox/templates/ipam/servicetemplate.html deleted file mode 100644 index f15e1d0501e..00000000000 --- a/netbox/templates/ipam/servicetemplate.html +++ /dev/null @@ -1 +0,0 @@ -{% extends 'generic/object.html' %} diff --git a/netbox/templates/ipam/vlantranslationpolicy.html b/netbox/templates/ipam/vlantranslationpolicy.html deleted file mode 100644 index f15e1d0501e..00000000000 --- a/netbox/templates/ipam/vlantranslationpolicy.html +++ /dev/null @@ -1 +0,0 @@ -{% extends 'generic/object.html' %} diff --git a/netbox/templates/ipam/vlantranslationrule.html b/netbox/templates/ipam/vlantranslationrule.html deleted file mode 100644 index f15e1d0501e..00000000000 --- a/netbox/templates/ipam/vlantranslationrule.html +++ /dev/null @@ -1 +0,0 @@ -{% extends 'generic/object.html' %} diff --git a/netbox/templates/ipam/vrf.html b/netbox/templates/ipam/vrf.html deleted file mode 100644 index f15e1d0501e..00000000000 --- a/netbox/templates/ipam/vrf.html +++ /dev/null @@ -1 +0,0 @@ -{% extends 'generic/object.html' %} diff --git a/netbox/templates/tenancy/contact.html b/netbox/templates/tenancy/contact.html deleted file mode 100644 index f15e1d0501e..00000000000 --- a/netbox/templates/tenancy/contact.html +++ /dev/null @@ -1 +0,0 @@ -{% extends 'generic/object.html' %} diff --git a/netbox/templates/tenancy/contactrole.html b/netbox/templates/tenancy/contactrole.html deleted file mode 100644 index f15e1d0501e..00000000000 --- a/netbox/templates/tenancy/contactrole.html +++ /dev/null @@ -1 +0,0 @@ -{% extends 'generic/object.html' %} diff --git a/netbox/templates/vpn/ikepolicy.html b/netbox/templates/vpn/ikepolicy.html deleted file mode 100644 index f15e1d0501e..00000000000 --- a/netbox/templates/vpn/ikepolicy.html +++ /dev/null @@ -1 +0,0 @@ -{% extends 'generic/object.html' %} diff --git a/netbox/templates/vpn/ikeproposal.html b/netbox/templates/vpn/ikeproposal.html deleted file mode 100644 index f15e1d0501e..00000000000 --- a/netbox/templates/vpn/ikeproposal.html +++ /dev/null @@ -1 +0,0 @@ -{% extends 'generic/object.html' %} diff --git a/netbox/templates/vpn/ipsecpolicy.html b/netbox/templates/vpn/ipsecpolicy.html deleted file mode 100644 index f15e1d0501e..00000000000 --- a/netbox/templates/vpn/ipsecpolicy.html +++ /dev/null @@ -1 +0,0 @@ -{% extends 'generic/object.html' %} diff --git a/netbox/templates/vpn/ipsecprofile.html b/netbox/templates/vpn/ipsecprofile.html deleted file mode 100644 index f15e1d0501e..00000000000 --- a/netbox/templates/vpn/ipsecprofile.html +++ /dev/null @@ -1 +0,0 @@ -{% extends 'generic/object.html' %} diff --git a/netbox/templates/vpn/ipsecproposal.html b/netbox/templates/vpn/ipsecproposal.html deleted file mode 100644 index f15e1d0501e..00000000000 --- a/netbox/templates/vpn/ipsecproposal.html +++ /dev/null @@ -1 +0,0 @@ -{% extends 'generic/object.html' %} diff --git a/netbox/templates/vpn/l2vpn.html b/netbox/templates/vpn/l2vpn.html deleted file mode 100644 index f15e1d0501e..00000000000 --- a/netbox/templates/vpn/l2vpn.html +++ /dev/null @@ -1 +0,0 @@ -{% extends 'generic/object.html' %} diff --git a/netbox/templates/vpn/l2vpntermination.html b/netbox/templates/vpn/l2vpntermination.html deleted file mode 100644 index f15e1d0501e..00000000000 --- a/netbox/templates/vpn/l2vpntermination.html +++ /dev/null @@ -1 +0,0 @@ -{% extends 'generic/object.html' %} diff --git a/netbox/templates/vpn/tunneltermination.html b/netbox/templates/vpn/tunneltermination.html deleted file mode 100644 index f15e1d0501e..00000000000 --- a/netbox/templates/vpn/tunneltermination.html +++ /dev/null @@ -1 +0,0 @@ -{% extends 'generic/object.html' %} diff --git a/netbox/templates/wireless/wirelesslan.html b/netbox/templates/wireless/wirelesslan.html deleted file mode 100644 index f15e1d0501e..00000000000 --- a/netbox/templates/wireless/wirelesslan.html +++ /dev/null @@ -1 +0,0 @@ -{% extends 'generic/object.html' %} diff --git a/netbox/templates/wireless/wirelesslink.html b/netbox/templates/wireless/wirelesslink.html deleted file mode 100644 index f15e1d0501e..00000000000 --- a/netbox/templates/wireless/wirelesslink.html +++ /dev/null @@ -1 +0,0 @@ -{% extends 'generic/object.html' %} diff --git a/netbox/tenancy/views.py b/netbox/tenancy/views.py index 7ebc1ab826c..08adf2d2911 100644 --- a/netbox/tenancy/views.py +++ b/netbox/tenancy/views.py @@ -328,6 +328,7 @@ class ContactRoleListView(generic.ObjectListView): @register_model_view(ContactRole) class ContactRoleView(GetRelatedModelsMixin, generic.ObjectView): queryset = ContactRole.objects.all() + template_name = 'generic/object.html' layout = layout.SimpleLayout( left_panels=[ OrganizationalObjectPanel(), @@ -402,6 +403,7 @@ class ContactListView(generic.ObjectListView): @register_model_view(Contact) class ContactView(generic.ObjectView): queryset = Contact.objects.all() + template_name = 'generic/object.html' layout = layout.SimpleLayout( left_panels=[ panels.ContactPanel(), diff --git a/netbox/utilities/views.py b/netbox/utilities/views.py index dcf8ed696c4..1ebd2b4e5a2 100644 --- a/netbox/utilities/views.py +++ b/netbox/utilities/views.py @@ -6,6 +6,8 @@ from django.core.exceptions import ImproperlyConfigured from django.db.models import QuerySet from django.http import HttpResponseForbidden +from django.template import TemplateDoesNotExist +from django.template.loader import get_template from django.urls import reverse from django.urls.exceptions import NoReverseMatch from django.utils.translation import gettext_lazy as _ @@ -29,6 +31,7 @@ 'TokenConditionalLoginRequiredMixin', 'ViewTab', 'get_action_url', + 'get_default_template', 'get_viewname', 'register_model_view', ) @@ -335,6 +338,19 @@ def get_action_url(model, action=None, rest_api=False, kwargs=None): return reverse(get_viewname(model, action, rest_api), kwargs=kwargs) +def get_default_template(model): + """ + Return the base template for the given model. If the presumed "{app}/{model}.html" template + does not exist, fall back to "generic/object.html". + """ + template_name = f'{model._meta.app_label}/{model._meta.model_name}.html' + try: + get_template(template_name) + return template_name + except TemplateDoesNotExist: + return 'generic/object.html' + + def register_model_view(model, name='', path=None, detail=True, kwargs=None): """ This decorator can be used to "attach" a view to any model in NetBox. This is typically used to inject diff --git a/netbox/vpn/views.py b/netbox/vpn/views.py index f365377ad84..602f780c102 100644 --- a/netbox/vpn/views.py +++ b/netbox/vpn/views.py @@ -208,6 +208,7 @@ class TunnelTerminationListView(generic.ObjectListView): @register_model_view(TunnelTermination) class TunnelTerminationView(generic.ObjectView): queryset = TunnelTermination.objects.all() + template_name = 'generic/object.html' layout = layout.SimpleLayout( left_panels=[ panels.TunnelTerminationPanel(), @@ -278,6 +279,7 @@ class IKEProposalListView(generic.ObjectListView): @register_model_view(IKEProposal) class IKEProposalView(generic.ObjectView): queryset = IKEProposal.objects.all() + template_name = 'generic/object.html' layout = layout.SimpleLayout( left_panels=[ panels.IKEProposalPanel(), @@ -351,6 +353,7 @@ class IKEPolicyListView(generic.ObjectListView): @register_model_view(IKEPolicy) class IKEPolicyView(GetRelatedModelsMixin, generic.ObjectView): queryset = IKEPolicy.objects.all() + template_name = 'generic/object.html' layout = layout.SimpleLayout( left_panels=[ panels.IKEPolicyPanel(), @@ -430,6 +433,7 @@ class IPSecProposalListView(generic.ObjectListView): @register_model_view(IPSecProposal) class IPSecProposalView(generic.ObjectView): queryset = IPSecProposal.objects.all() + template_name = 'generic/object.html' layout = layout.SimpleLayout( left_panels=[ panels.IPSecProposalPanel(), @@ -503,6 +507,7 @@ class IPSecPolicyListView(generic.ObjectListView): @register_model_view(IPSecPolicy) class IPSecPolicyView(GetRelatedModelsMixin, generic.ObjectView): queryset = IPSecPolicy.objects.all() + template_name = 'generic/object.html' layout = layout.SimpleLayout( left_panels=[ panels.IPSecPolicyPanel(), @@ -582,6 +587,7 @@ class IPSecProfileListView(generic.ObjectListView): @register_model_view(IPSecProfile) class IPSecProfileView(generic.ObjectView): queryset = IPSecProfile.objects.all() + template_name = 'generic/object.html' layout = layout.SimpleLayout( left_panels=[ panels.IPSecProfilePanel(), @@ -650,6 +656,7 @@ class L2VPNListView(generic.ObjectListView): @register_model_view(L2VPN) class L2VPNView(generic.ObjectView): queryset = L2VPN.objects.all() + template_name = 'generic/object.html' layout = layout.Layout( layout.Row( layout.Column( @@ -764,6 +771,7 @@ class L2VPNTerminationListView(generic.ObjectListView): @register_model_view(L2VPNTermination) class L2VPNTerminationView(generic.ObjectView): queryset = L2VPNTermination.objects.all() + template_name = 'generic/object.html' layout = layout.SimpleLayout( left_panels=[ panels.L2VPNTerminationPanel(), diff --git a/netbox/wireless/views.py b/netbox/wireless/views.py index 422b46cc5f6..9a1e9efda23 100644 --- a/netbox/wireless/views.py +++ b/netbox/wireless/views.py @@ -143,6 +143,7 @@ class WirelessLANListView(generic.ObjectListView): @register_model_view(WirelessLAN) class WirelessLANView(generic.ObjectView): queryset = WirelessLAN.objects.all() + template_name = 'generic/object.html' layout = layout.SimpleLayout( left_panels=[ panels.WirelessLANPanel(), @@ -218,6 +219,7 @@ class WirelessLinkListView(generic.ObjectListView): @register_model_view(WirelessLink) class WirelessLinkView(generic.ObjectView): queryset = WirelessLink.objects.all() + template_name = 'generic/object.html' layout = layout.SimpleLayout( left_panels=[ panels.WirelessLinkInterfacePanel('interface_a', title=_('Interface A')),