mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-14 01:41:22 -06:00
parent
1508e3a770
commit
864db469ba
@ -117,6 +117,8 @@ For more information about database migrations, see the [Django documentation](h
|
|||||||
|
|
||||||
::: netbox.models.features.CloningMixin
|
::: netbox.models.features.CloningMixin
|
||||||
|
|
||||||
|
::: netbox.models.features.ContactsMixin
|
||||||
|
|
||||||
::: netbox.models.features.CustomLinksMixin
|
::: netbox.models.features.CustomLinksMixin
|
||||||
|
|
||||||
::: netbox.models.features.CustomFieldsMixin
|
::: netbox.models.features.CustomFieldsMixin
|
||||||
|
@ -5,7 +5,6 @@ from django.utils.translation import gettext_lazy as _
|
|||||||
|
|
||||||
from dcim.views import PathTraceView
|
from dcim.views import PathTraceView
|
||||||
from netbox.views import generic
|
from netbox.views import generic
|
||||||
from tenancy.views import ObjectContactsView
|
|
||||||
from utilities.forms import ConfirmationForm
|
from utilities.forms import ConfirmationForm
|
||||||
from utilities.query import count_related
|
from utilities.query import count_related
|
||||||
from utilities.views import GetRelatedModelsMixin, register_model_view
|
from utilities.views import GetRelatedModelsMixin, register_model_view
|
||||||
@ -74,11 +73,6 @@ class ProviderBulkDeleteView(generic.BulkDeleteView):
|
|||||||
table = tables.ProviderTable
|
table = tables.ProviderTable
|
||||||
|
|
||||||
|
|
||||||
@register_model_view(Provider, 'contacts')
|
|
||||||
class ProviderContactsView(ObjectContactsView):
|
|
||||||
queryset = Provider.objects.all()
|
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# ProviderAccounts
|
# ProviderAccounts
|
||||||
#
|
#
|
||||||
@ -141,11 +135,6 @@ class ProviderAccountBulkDeleteView(generic.BulkDeleteView):
|
|||||||
table = tables.ProviderAccountTable
|
table = tables.ProviderAccountTable
|
||||||
|
|
||||||
|
|
||||||
@register_model_view(ProviderAccount, 'contacts')
|
|
||||||
class ProviderAccountContactsView(ObjectContactsView):
|
|
||||||
queryset = ProviderAccount.objects.all()
|
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Provider networks
|
# Provider networks
|
||||||
#
|
#
|
||||||
@ -413,11 +402,6 @@ class CircuitSwapTerminations(generic.ObjectEditView):
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
@register_model_view(Circuit, 'contacts')
|
|
||||||
class CircuitContactsView(ObjectContactsView):
|
|
||||||
queryset = Circuit.objects.all()
|
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Circuit terminations
|
# Circuit terminations
|
||||||
#
|
#
|
||||||
|
@ -19,7 +19,6 @@ from ipam.models import ASN, IPAddress, Prefix, VLANGroup
|
|||||||
from ipam.tables import InterfaceVLANTable, VLANTranslationRuleTable
|
from ipam.tables import InterfaceVLANTable, VLANTranslationRuleTable
|
||||||
from netbox.constants import DEFAULT_ACTION_PERMISSIONS
|
from netbox.constants import DEFAULT_ACTION_PERMISSIONS
|
||||||
from netbox.views import generic
|
from netbox.views import generic
|
||||||
from tenancy.views import ObjectContactsView
|
|
||||||
from utilities.forms import ConfirmationForm
|
from utilities.forms import ConfirmationForm
|
||||||
from utilities.paginator import EnhancedPaginator, get_paginate_count
|
from utilities.paginator import EnhancedPaginator, get_paginate_count
|
||||||
from utilities.permissions import get_permission_for_model
|
from utilities.permissions import get_permission_for_model
|
||||||
@ -304,11 +303,6 @@ class RegionBulkDeleteView(generic.BulkDeleteView):
|
|||||||
table = tables.RegionTable
|
table = tables.RegionTable
|
||||||
|
|
||||||
|
|
||||||
@register_model_view(Region, 'contacts')
|
|
||||||
class RegionContactsView(ObjectContactsView):
|
|
||||||
queryset = Region.objects.all()
|
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Site groups
|
# Site groups
|
||||||
#
|
#
|
||||||
@ -412,11 +406,6 @@ class SiteGroupBulkDeleteView(generic.BulkDeleteView):
|
|||||||
table = tables.SiteGroupTable
|
table = tables.SiteGroupTable
|
||||||
|
|
||||||
|
|
||||||
@register_model_view(SiteGroup, 'contacts')
|
|
||||||
class SiteGroupContactsView(ObjectContactsView):
|
|
||||||
queryset = SiteGroup.objects.all()
|
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Sites
|
# Sites
|
||||||
#
|
#
|
||||||
@ -494,11 +483,6 @@ class SiteBulkDeleteView(generic.BulkDeleteView):
|
|||||||
table = tables.SiteTable
|
table = tables.SiteTable
|
||||||
|
|
||||||
|
|
||||||
@register_model_view(Site, 'contacts')
|
|
||||||
class SiteContactsView(ObjectContactsView):
|
|
||||||
queryset = Site.objects.all()
|
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Locations
|
# Locations
|
||||||
#
|
#
|
||||||
@ -596,11 +580,6 @@ class LocationBulkDeleteView(generic.BulkDeleteView):
|
|||||||
table = tables.LocationTable
|
table = tables.LocationTable
|
||||||
|
|
||||||
|
|
||||||
@register_model_view(Location, 'contacts')
|
|
||||||
class LocationContactsView(ObjectContactsView):
|
|
||||||
queryset = Location.objects.all()
|
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Rack roles
|
# Rack roles
|
||||||
#
|
#
|
||||||
@ -887,11 +866,6 @@ class RackBulkDeleteView(generic.BulkDeleteView):
|
|||||||
table = tables.RackTable
|
table = tables.RackTable
|
||||||
|
|
||||||
|
|
||||||
@register_model_view(Rack, 'contacts')
|
|
||||||
class RackContactsView(ObjectContactsView):
|
|
||||||
queryset = Rack.objects.all()
|
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Rack reservations
|
# Rack reservations
|
||||||
#
|
#
|
||||||
@ -1029,11 +1003,6 @@ class ManufacturerBulkDeleteView(generic.BulkDeleteView):
|
|||||||
table = tables.ManufacturerTable
|
table = tables.ManufacturerTable
|
||||||
|
|
||||||
|
|
||||||
@register_model_view(Manufacturer, 'contacts')
|
|
||||||
class ManufacturerContactsView(ObjectContactsView):
|
|
||||||
queryset = Manufacturer.objects.all()
|
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Device types
|
# Device types
|
||||||
#
|
#
|
||||||
@ -2360,11 +2329,6 @@ class DeviceBulkRenameView(generic.BulkRenameView):
|
|||||||
table = tables.DeviceTable
|
table = tables.DeviceTable
|
||||||
|
|
||||||
|
|
||||||
@register_model_view(Device, 'contacts')
|
|
||||||
class DeviceContactsView(ObjectContactsView):
|
|
||||||
queryset = Device.objects.all()
|
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Modules
|
# Modules
|
||||||
#
|
#
|
||||||
@ -3924,11 +3888,6 @@ class PowerPanelBulkDeleteView(generic.BulkDeleteView):
|
|||||||
table = tables.PowerPanelTable
|
table = tables.PowerPanelTable
|
||||||
|
|
||||||
|
|
||||||
@register_model_view(PowerPanel, 'contacts')
|
|
||||||
class PowerPanelContactsView(ObjectContactsView):
|
|
||||||
queryset = PowerPanel.objects.all()
|
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Power feeds
|
# Power feeds
|
||||||
#
|
#
|
||||||
|
@ -11,7 +11,6 @@ from dcim.forms import InterfaceFilterForm
|
|||||||
from dcim.models import Interface, Site
|
from dcim.models import Interface, Site
|
||||||
from ipam.tables import VLANTranslationRuleTable
|
from ipam.tables import VLANTranslationRuleTable
|
||||||
from netbox.views import generic
|
from netbox.views import generic
|
||||||
from tenancy.views import ObjectContactsView
|
|
||||||
from utilities.query import count_related
|
from utilities.query import count_related
|
||||||
from utilities.tables import get_table_ordering
|
from utilities.tables import get_table_ordering
|
||||||
from utilities.views import GetRelatedModelsMixin, ViewTab, register_model_view
|
from utilities.views import GetRelatedModelsMixin, ViewTab, register_model_view
|
||||||
@ -434,11 +433,6 @@ class AggregateBulkDeleteView(generic.BulkDeleteView):
|
|||||||
table = tables.AggregateTable
|
table = tables.AggregateTable
|
||||||
|
|
||||||
|
|
||||||
@register_model_view(Aggregate, 'contacts')
|
|
||||||
class AggregateContactsView(ObjectContactsView):
|
|
||||||
queryset = Aggregate.objects.all()
|
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Prefix/VLAN roles
|
# Prefix/VLAN roles
|
||||||
#
|
#
|
||||||
@ -684,11 +678,6 @@ class PrefixBulkDeleteView(generic.BulkDeleteView):
|
|||||||
table = tables.PrefixTable
|
table = tables.PrefixTable
|
||||||
|
|
||||||
|
|
||||||
@register_model_view(Prefix, 'contacts')
|
|
||||||
class PrefixContactsView(ObjectContactsView):
|
|
||||||
queryset = Prefix.objects.all()
|
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# IP Ranges
|
# IP Ranges
|
||||||
#
|
#
|
||||||
@ -778,11 +767,6 @@ class IPRangeBulkDeleteView(generic.BulkDeleteView):
|
|||||||
table = tables.IPRangeTable
|
table = tables.IPRangeTable
|
||||||
|
|
||||||
|
|
||||||
@register_model_view(IPRange, 'contacts')
|
|
||||||
class IPRangeContactsView(ObjectContactsView):
|
|
||||||
queryset = IPRange.objects.all()
|
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# IP addresses
|
# IP addresses
|
||||||
#
|
#
|
||||||
@ -964,11 +948,6 @@ class IPAddressRelatedIPsView(generic.ObjectChildrenView):
|
|||||||
return parent.get_related_ips().restrict(request.user, 'view')
|
return parent.get_related_ips().restrict(request.user, 'view')
|
||||||
|
|
||||||
|
|
||||||
@register_model_view(IPAddress, 'contacts')
|
|
||||||
class IPAddressContactsView(ObjectContactsView):
|
|
||||||
queryset = IPAddress.objects.all()
|
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# VLAN groups
|
# VLAN groups
|
||||||
#
|
#
|
||||||
@ -1476,8 +1455,3 @@ class ServiceBulkDeleteView(generic.BulkDeleteView):
|
|||||||
queryset = Service.objects.prefetch_related('device', 'virtual_machine')
|
queryset = Service.objects.prefetch_related('device', 'virtual_machine')
|
||||||
filterset = filtersets.ServiceFilterSet
|
filterset = filtersets.ServiceFilterSet
|
||||||
table = tables.ServiceTable
|
table = tables.ServiceTable
|
||||||
|
|
||||||
|
|
||||||
@register_model_view(Service, 'contacts')
|
|
||||||
class ServiceContactsView(ObjectContactsView):
|
|
||||||
queryset = Service.objects.all()
|
|
||||||
|
@ -353,7 +353,7 @@ class ImageAttachmentsMixin(models.Model):
|
|||||||
|
|
||||||
class ContactsMixin(models.Model):
|
class ContactsMixin(models.Model):
|
||||||
"""
|
"""
|
||||||
Enables the assignments of Contacts (via ContactAssignment).
|
Enables the assignment of Contacts to a model (via ContactAssignment).
|
||||||
"""
|
"""
|
||||||
contacts = GenericRelation(
|
contacts = GenericRelation(
|
||||||
to='tenancy.ContactAssignment',
|
to='tenancy.ContactAssignment',
|
||||||
@ -368,7 +368,8 @@ class ContactsMixin(models.Model):
|
|||||||
"""
|
"""
|
||||||
Return a `QuerySet` matching all contacts assigned to this object.
|
Return a `QuerySet` matching all contacts assigned to this object.
|
||||||
|
|
||||||
:param inherited: If `True`, inherited contacts from parent objects are included.
|
Args:
|
||||||
|
inherited: If `True`, inherited contacts from parent objects are included.
|
||||||
"""
|
"""
|
||||||
from tenancy.models import ContactAssignment
|
from tenancy.models import ContactAssignment
|
||||||
from . import NestedGroupModel
|
from . import NestedGroupModel
|
||||||
@ -659,6 +660,10 @@ def register_models(*models):
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Register applicable feature views for the model
|
# Register applicable feature views for the model
|
||||||
|
if issubclass(model, ContactsMixin):
|
||||||
|
register_model_view(model, 'contacts', kwargs={'model': model})(
|
||||||
|
'netbox.views.generic.ObjectContactsView'
|
||||||
|
)
|
||||||
if issubclass(model, JournalingMixin):
|
if issubclass(model, JournalingMixin):
|
||||||
register_model_view(model, 'journal', kwargs={'model': model})(
|
register_model_view(model, 'journal', kwargs={'model': model})(
|
||||||
'netbox.views.generic.ObjectJournalView'
|
'netbox.views.generic.ObjectJournalView'
|
||||||
|
@ -12,13 +12,19 @@ from core.tables import JobTable, ObjectChangeTable
|
|||||||
from extras.forms import JournalEntryForm
|
from extras.forms import JournalEntryForm
|
||||||
from extras.models import JournalEntry
|
from extras.models import JournalEntry
|
||||||
from extras.tables import JournalEntryTable
|
from extras.tables import JournalEntryTable
|
||||||
|
from tenancy.models import ContactAssignment
|
||||||
|
from tenancy.tables import ContactAssignmentTable
|
||||||
|
from tenancy.filtersets import ContactAssignmentFilterSet
|
||||||
|
from tenancy.forms import ContactAssignmentFilterForm
|
||||||
from utilities.permissions import get_permission_for_model
|
from utilities.permissions import get_permission_for_model
|
||||||
from utilities.views import ConditionalLoginRequiredMixin, GetReturnURLMixin, ViewTab
|
from utilities.views import ConditionalLoginRequiredMixin, GetReturnURLMixin, ViewTab
|
||||||
from .base import BaseMultiObjectView
|
from .base import BaseMultiObjectView
|
||||||
|
from .object_views import ObjectChildrenView
|
||||||
|
|
||||||
__all__ = (
|
__all__ = (
|
||||||
'BulkSyncDataView',
|
'BulkSyncDataView',
|
||||||
'ObjectChangeLogView',
|
'ObjectChangeLogView',
|
||||||
|
'ObjectContactsView',
|
||||||
'ObjectJobsView',
|
'ObjectJobsView',
|
||||||
'ObjectJournalView',
|
'ObjectJournalView',
|
||||||
'ObjectSyncDataView',
|
'ObjectSyncDataView',
|
||||||
@ -244,3 +250,25 @@ class BulkSyncDataView(GetReturnURLMixin, BaseMultiObjectView):
|
|||||||
))
|
))
|
||||||
|
|
||||||
return redirect(self.get_return_url(request))
|
return redirect(self.get_return_url(request))
|
||||||
|
|
||||||
|
|
||||||
|
class ObjectContactsView(ObjectChildrenView):
|
||||||
|
child_model = ContactAssignment
|
||||||
|
table = ContactAssignmentTable
|
||||||
|
filterset = ContactAssignmentFilterSet
|
||||||
|
filterset_form = ContactAssignmentFilterForm
|
||||||
|
template_name = 'tenancy/object_contacts.html'
|
||||||
|
tab = ViewTab(
|
||||||
|
label=_('Contacts'),
|
||||||
|
badge=lambda obj: obj.get_contacts().count(),
|
||||||
|
permission='tenancy.view_contactassignment',
|
||||||
|
weight=5000
|
||||||
|
)
|
||||||
|
|
||||||
|
def dispatch(self, request, *args, **kwargs):
|
||||||
|
model = kwargs.pop('model')
|
||||||
|
self.queryset = model.objects.all()
|
||||||
|
return super().dispatch(request, *args, **kwargs)
|
||||||
|
|
||||||
|
def get_children(self, request, parent):
|
||||||
|
return parent.get_contacts().restrict(request.user, 'view').order_by('priority', 'contact', 'role')
|
||||||
|
@ -1,31 +1,13 @@
|
|||||||
from django.contrib.contenttypes.models import ContentType
|
from django.contrib.contenttypes.models import ContentType
|
||||||
from django.shortcuts import get_object_or_404
|
from django.shortcuts import get_object_or_404
|
||||||
from django.utils.translation import gettext_lazy as _
|
|
||||||
|
|
||||||
from netbox.views import generic
|
from netbox.views import generic
|
||||||
from utilities.query import count_related
|
from utilities.query import count_related
|
||||||
from utilities.views import GetRelatedModelsMixin, ViewTab, register_model_view
|
from utilities.views import GetRelatedModelsMixin, register_model_view
|
||||||
from . import filtersets, forms, tables
|
from . import filtersets, forms, tables
|
||||||
from .models import *
|
from .models import *
|
||||||
|
|
||||||
|
|
||||||
class ObjectContactsView(generic.ObjectChildrenView):
|
|
||||||
child_model = ContactAssignment
|
|
||||||
table = tables.ContactAssignmentTable
|
|
||||||
filterset = filtersets.ContactAssignmentFilterSet
|
|
||||||
filterset_form = forms.ContactAssignmentFilterForm
|
|
||||||
template_name = 'tenancy/object_contacts.html'
|
|
||||||
tab = ViewTab(
|
|
||||||
label=_('Contacts'),
|
|
||||||
badge=lambda obj: obj.get_contacts().count(),
|
|
||||||
permission='tenancy.view_contactassignment',
|
|
||||||
weight=5000
|
|
||||||
)
|
|
||||||
|
|
||||||
def get_children(self, request, parent):
|
|
||||||
return parent.get_contacts().restrict(request.user, 'view').order_by('priority', 'contact', 'role')
|
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Tenant groups
|
# Tenant groups
|
||||||
#
|
#
|
||||||
@ -156,11 +138,6 @@ class TenantBulkDeleteView(generic.BulkDeleteView):
|
|||||||
table = tables.TenantTable
|
table = tables.TenantTable
|
||||||
|
|
||||||
|
|
||||||
@register_model_view(Tenant, 'contacts')
|
|
||||||
class TenantContactsView(ObjectContactsView):
|
|
||||||
queryset = Tenant.objects.all()
|
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Contact groups
|
# Contact groups
|
||||||
#
|
#
|
||||||
|
@ -16,7 +16,6 @@ from ipam.models import IPAddress
|
|||||||
from ipam.tables import InterfaceVLANTable, VLANTranslationRuleTable
|
from ipam.tables import InterfaceVLANTable, VLANTranslationRuleTable
|
||||||
from netbox.constants import DEFAULT_ACTION_PERMISSIONS
|
from netbox.constants import DEFAULT_ACTION_PERMISSIONS
|
||||||
from netbox.views import generic
|
from netbox.views import generic
|
||||||
from tenancy.views import ObjectContactsView
|
|
||||||
from utilities.query import count_related
|
from utilities.query import count_related
|
||||||
from utilities.query_functions import CollateAsChar
|
from utilities.query_functions import CollateAsChar
|
||||||
from utilities.views import GetRelatedModelsMixin, ViewTab, register_model_view
|
from utilities.views import GetRelatedModelsMixin, ViewTab, register_model_view
|
||||||
@ -148,11 +147,6 @@ class ClusterGroupBulkDeleteView(generic.BulkDeleteView):
|
|||||||
table = tables.ClusterGroupTable
|
table = tables.ClusterGroupTable
|
||||||
|
|
||||||
|
|
||||||
@register_model_view(ClusterGroup, 'contacts')
|
|
||||||
class ClusterGroupContactsView(ObjectContactsView):
|
|
||||||
queryset = ClusterGroup.objects.all()
|
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Clusters
|
# Clusters
|
||||||
#
|
#
|
||||||
@ -344,11 +338,6 @@ class ClusterRemoveDevicesView(generic.ObjectEditView):
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
@register_model_view(Cluster, 'contacts')
|
|
||||||
class ClusterContactsView(ObjectContactsView):
|
|
||||||
queryset = Cluster.objects.all()
|
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Virtual machines
|
# Virtual machines
|
||||||
#
|
#
|
||||||
@ -509,11 +498,6 @@ class VirtualMachineBulkDeleteView(generic.BulkDeleteView):
|
|||||||
table = tables.VirtualMachineTable
|
table = tables.VirtualMachineTable
|
||||||
|
|
||||||
|
|
||||||
@register_model_view(VirtualMachine, 'contacts')
|
|
||||||
class VirtualMachineContactsView(ObjectContactsView):
|
|
||||||
queryset = VirtualMachine.objects.all()
|
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# VM interfaces
|
# VM interfaces
|
||||||
#
|
#
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
from ipam.tables import RouteTargetTable
|
from ipam.tables import RouteTargetTable
|
||||||
from netbox.views import generic
|
from netbox.views import generic
|
||||||
from tenancy.views import ObjectContactsView
|
|
||||||
from utilities.query import count_related
|
from utilities.query import count_related
|
||||||
from utilities.views import GetRelatedModelsMixin, register_model_view
|
from utilities.views import GetRelatedModelsMixin, register_model_view
|
||||||
from . import filtersets, forms, tables
|
from . import filtersets, forms, tables
|
||||||
@ -497,11 +496,6 @@ class L2VPNBulkDeleteView(generic.BulkDeleteView):
|
|||||||
table = tables.L2VPNTable
|
table = tables.L2VPNTable
|
||||||
|
|
||||||
|
|
||||||
@register_model_view(L2VPN, 'contacts')
|
|
||||||
class L2VPNContactsView(ObjectContactsView):
|
|
||||||
queryset = L2VPN.objects.all()
|
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# L2VPN terminations
|
# L2VPN terminations
|
||||||
#
|
#
|
||||||
|
Loading…
Reference in New Issue
Block a user