Introduce ContactsMixin

This commit is contained in:
Jeremy Stretch 2023-08-04 09:43:44 -04:00
parent 14e23c3d00
commit 2afce6c94b
11 changed files with 40 additions and 94 deletions

View File

@ -1,4 +1,3 @@
from django.contrib.contenttypes.fields import GenericRelation
from django.core.exceptions import ValidationError
from django.db import models
from django.urls import reverse
@ -7,7 +6,7 @@ from django.utils.translation import gettext_lazy as _
from circuits.choices import *
from dcim.models import CabledObjectModel
from netbox.models import ChangeLoggedModel, OrganizationalModel, PrimaryModel
from netbox.models.features import CustomFieldsMixin, CustomLinksMixin, ImageAttachmentsMixin, TagsMixin
from netbox.models.features import ContactsMixin, CustomFieldsMixin, CustomLinksMixin, ImageAttachmentsMixin, TagsMixin
__all__ = (
'Circuit',
@ -30,7 +29,7 @@ class CircuitType(OrganizationalModel):
verbose_name_plural = _('circuit types')
class Circuit(ImageAttachmentsMixin, PrimaryModel):
class Circuit(ContactsMixin, ImageAttachmentsMixin, PrimaryModel):
"""
A communications circuit connects two points. Each Circuit belongs to a Provider; Providers may have multiple
circuits. Each circuit is also assigned a CircuitType and a Site, and may optionally be assigned to a particular
@ -88,11 +87,6 @@ class Circuit(ImageAttachmentsMixin, PrimaryModel):
help_text=_("Committed rate")
)
# Generic relations
contacts = GenericRelation(
to='tenancy.ContactAssignment'
)
# Cache associated CircuitTerminations
termination_a = models.ForeignKey(
to='circuits.CircuitTermination',

View File

@ -1,10 +1,10 @@
from django.contrib.contenttypes.fields import GenericRelation
from django.db import models
from django.db.models import Q
from django.urls import reverse
from django.utils.translation import gettext_lazy as _
from netbox.models import PrimaryModel
from netbox.models.features import ContactsMixin
__all__ = (
'ProviderNetwork',
@ -13,7 +13,7 @@ __all__ = (
)
class Provider(PrimaryModel):
class Provider(ContactsMixin, PrimaryModel):
"""
Each Circuit belongs to a Provider. This is usually a telecommunications company or similar organization. This model
stores information pertinent to the user's relationship with the Provider.
@ -35,11 +35,6 @@ class Provider(PrimaryModel):
blank=True
)
# Generic relations
contacts = GenericRelation(
to='tenancy.ContactAssignment'
)
clone_fields = ()
class Meta:
@ -54,7 +49,7 @@ class Provider(PrimaryModel):
return reverse('circuits:provider', args=[self.pk])
class ProviderAccount(PrimaryModel):
class ProviderAccount(ContactsMixin, PrimaryModel):
"""
This is a discrete account within a provider. Each Circuit belongs to a Provider Account.
"""
@ -73,11 +68,6 @@ class ProviderAccount(PrimaryModel):
blank=True
)
# Generic relations
contacts = GenericRelation(
to='tenancy.ContactAssignment'
)
clone_fields = ('provider', )
class Meta:

View File

@ -3,7 +3,6 @@ import yaml
from functools import cached_property
from django.contrib.contenttypes.fields import GenericRelation
from django.core.exceptions import ValidationError
from django.core.validators import MaxValueValidator, MinValueValidator
from django.db import models
@ -20,7 +19,7 @@ from extras.models import ConfigContextModel
from extras.querysets import ConfigContextModelQuerySet
from netbox.config import ConfigItem
from netbox.models import OrganizationalModel, PrimaryModel
from netbox.models.features import ImageAttachmentsMixin
from netbox.models.features import ContactsMixin, ImageAttachmentsMixin
from utilities.choices import ColorChoices
from utilities.fields import ColorField, CounterCacheField, NaturalOrderingField
from utilities.tracking import TrackingModelMixin
@ -45,15 +44,10 @@ __all__ = (
# Device Types
#
class Manufacturer(OrganizationalModel):
class Manufacturer(ContactsMixin, OrganizationalModel):
"""
A Manufacturer represents a company which produces hardware devices; for example, Juniper or Dell.
"""
# Generic relations
contacts = GenericRelation(
to='tenancy.ContactAssignment'
)
class Meta:
ordering = ('name',)
verbose_name = _('manufacturer')
@ -531,7 +525,7 @@ def update_interface_bridges(device, interface_templates, module=None):
interface.save()
class Device(ImageAttachmentsMixin, PrimaryModel, ConfigContextModel, TrackingModelMixin):
class Device(ContactsMixin, ImageAttachmentsMixin, PrimaryModel, ConfigContextModel, TrackingModelMixin):
"""
A Device represents a piece of physical hardware mounted within a Rack. Each Device is assigned a DeviceType,
DeviceRole, and (optionally) a Platform. Device names are not required, however if one is set it must be unique.
@ -758,11 +752,6 @@ class Device(ImageAttachmentsMixin, PrimaryModel, ConfigContextModel, TrackingMo
to_field='device'
)
# Generic relations
contacts = GenericRelation(
to='tenancy.ContactAssignment'
)
objects = ConfigContextModelQuerySet.as_manager()
clone_fields = (

View File

@ -1,4 +1,3 @@
from django.contrib.contenttypes.fields import GenericRelation
from django.core.exceptions import ValidationError
from django.core.validators import MaxValueValidator, MinValueValidator
from django.db import models
@ -8,7 +7,7 @@ from django.utils.translation import gettext_lazy as _
from dcim.choices import *
from netbox.config import ConfigItem
from netbox.models import PrimaryModel
from netbox.models.features import ImageAttachmentsMixin
from netbox.models.features import ContactsMixin, ImageAttachmentsMixin
from utilities.validators import ExclusionValidator
from .device_components import CabledObjectModel, PathEndpoint
@ -22,7 +21,7 @@ __all__ = (
# Power
#
class PowerPanel(ImageAttachmentsMixin, PrimaryModel):
class PowerPanel(ContactsMixin, ImageAttachmentsMixin, PrimaryModel):
"""
A distribution point for electrical power; e.g. a data center RPP.
"""
@ -41,11 +40,6 @@ class PowerPanel(ImageAttachmentsMixin, PrimaryModel):
max_length=100
)
# Generic relations
contacts = GenericRelation(
to='tenancy.ContactAssignment'
)
prerequisite_models = (
'dcim.Site',
)

View File

@ -15,7 +15,7 @@ from dcim.choices import *
from dcim.constants import *
from dcim.svg import RackElevationSVG
from netbox.models import OrganizationalModel, PrimaryModel
from netbox.models.features import ImageAttachmentsMixin
from netbox.models.features import ContactsMixin, ImageAttachmentsMixin
from utilities.choices import ColorChoices
from utilities.fields import ColorField, NaturalOrderingField
from utilities.utils import array_to_string, drange, to_grams
@ -53,7 +53,7 @@ class RackRole(OrganizationalModel):
return reverse('dcim:rackrole', args=[self.pk])
class Rack(ImageAttachmentsMixin, PrimaryModel, WeightMixin):
class Rack(ContactsMixin, ImageAttachmentsMixin, PrimaryModel, WeightMixin):
"""
Devices are housed within Racks. Each rack has a defined height measured in rack units, and a front and rear face.
Each Rack is assigned to a Site and (optionally) a Location.
@ -194,9 +194,6 @@ class Rack(ImageAttachmentsMixin, PrimaryModel, WeightMixin):
object_id_field='scope_id',
related_query_name='rack'
)
contacts = GenericRelation(
to='tenancy.ContactAssignment'
)
clone_fields = (
'site', 'location', 'tenant', 'status', 'role', 'type', 'width', 'u_height', 'desc_units', 'outer_width',

View File

@ -8,7 +8,7 @@ from timezone_field import TimeZoneField
from dcim.choices import *
from dcim.constants import *
from netbox.models import NestedGroupModel, PrimaryModel
from netbox.models.features import ImageAttachmentsMixin
from netbox.models.features import ContactsMixin, ImageAttachmentsMixin
from utilities.fields import NaturalOrderingField
__all__ = (
@ -23,22 +23,18 @@ __all__ = (
# Regions
#
class Region(NestedGroupModel):
class Region(ContactsMixin, NestedGroupModel):
"""
A region represents a geographic collection of sites. For example, you might create regions representing countries,
states, and/or cities. Regions are recursively nested into a hierarchy: all sites belonging to a child region are
also considered to be members of its parent and ancestor region(s).
"""
# Generic relations
vlan_groups = GenericRelation(
to='ipam.VLANGroup',
content_type_field='scope_type',
object_id_field='scope_id',
related_query_name='region'
)
contacts = GenericRelation(
to='tenancy.ContactAssignment'
)
class Meta:
constraints = (
@ -80,22 +76,18 @@ class Region(NestedGroupModel):
# Site groups
#
class SiteGroup(NestedGroupModel):
class SiteGroup(ContactsMixin, NestedGroupModel):
"""
A site group is an arbitrary grouping of sites. For example, you might have corporate sites and customer sites; and
within corporate sites you might distinguish between offices and data centers. Like regions, site groups can be
nested recursively to form a hierarchy.
"""
# Generic relations
vlan_groups = GenericRelation(
to='ipam.VLANGroup',
content_type_field='scope_type',
object_id_field='scope_id',
related_query_name='site_group'
)
contacts = GenericRelation(
to='tenancy.ContactAssignment'
)
class Meta:
constraints = (
@ -137,7 +129,7 @@ class SiteGroup(NestedGroupModel):
# Sites
#
class Site(ImageAttachmentsMixin, PrimaryModel):
class Site(ContactsMixin, ImageAttachmentsMixin, PrimaryModel):
"""
A Site represents a geographic location within a network; typically a building or campus. The optional facility
field can be used to include an external designation, such as a data center name (e.g. Equinix SV6).
@ -235,9 +227,6 @@ class Site(ImageAttachmentsMixin, PrimaryModel):
object_id_field='scope_id',
related_query_name='site'
)
contacts = GenericRelation(
to='tenancy.ContactAssignment'
)
clone_fields = (
'status', 'region', 'group', 'tenant', 'facility', 'time_zone', 'physical_address', 'shipping_address',
@ -263,7 +252,7 @@ class Site(ImageAttachmentsMixin, PrimaryModel):
# Locations
#
class Location(ImageAttachmentsMixin, NestedGroupModel):
class Location(ContactsMixin, ImageAttachmentsMixin, NestedGroupModel):
"""
A Location represents a subgroup of Racks and/or Devices within a Site. A Location may represent a building within a
site, or a room within a building, for example.
@ -294,9 +283,6 @@ class Location(ImageAttachmentsMixin, NestedGroupModel):
object_id_field='scope_id',
related_query_name='location'
)
contacts = GenericRelation(
to='tenancy.ContactAssignment'
)
clone_fields = ('site', 'parent', 'status', 'tenant', 'description')
prerequisite_models = (

View File

@ -1,4 +1,4 @@
from django.contrib.contenttypes.fields import GenericRelation, GenericForeignKey
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ValidationError
from django.db import models
@ -9,6 +9,7 @@ from django.utils.translation import gettext_lazy as _
from ipam.choices import L2VPNTypeChoices
from ipam.constants import L2VPN_ASSIGNMENT_MODELS
from netbox.models import NetBoxModel, PrimaryModel
from netbox.models.features import ContactsMixin
__all__ = (
'L2VPN',
@ -16,7 +17,7 @@ __all__ = (
)
class L2VPN(PrimaryModel):
class L2VPN(ContactsMixin, PrimaryModel):
name = models.CharField(
verbose_name=_('name'),
max_length=100,
@ -54,9 +55,6 @@ class L2VPN(PrimaryModel):
blank=True,
null=True
)
contacts = GenericRelation(
to='tenancy.ContactAssignment'
)
clone_fields = ('type',)

View File

@ -25,6 +25,7 @@ __all__ = (
'BookmarksMixin',
'ChangeLoggingMixin',
'CloningMixin',
'ContactsMixin',
'CustomFieldsMixin',
'CustomLinksMixin',
'CustomValidationMixin',
@ -320,6 +321,18 @@ class ImageAttachmentsMixin(models.Model):
abstract = True
class ContactsMixin(models.Model):
"""
Enables the assignments of Contacts (via ContactAssignment).
"""
contacts = GenericRelation(
to='tenancy.ContactAssignment'
)
class Meta:
abstract = True
class BookmarksMixin(models.Model):
"""
Enables support for user bookmarks.

View File

@ -1,10 +1,10 @@
from django.contrib.contenttypes.fields import GenericRelation
from django.db import models
from django.db.models import Q
from django.urls import reverse
from django.utils.translation import gettext_lazy as _
from netbox.models import NestedGroupModel, PrimaryModel
from netbox.models.features import ContactsMixin
__all__ = (
'Tenant',
@ -36,7 +36,7 @@ class TenantGroup(NestedGroupModel):
return reverse('tenancy:tenantgroup', args=[self.pk])
class Tenant(PrimaryModel):
class Tenant(ContactsMixin, PrimaryModel):
"""
A Tenant represents an organization served by the NetBox owner. This is typically a customer or an internal
department.
@ -57,11 +57,6 @@ class Tenant(PrimaryModel):
null=True
)
# Generic relations
contacts = GenericRelation(
to='tenancy.ContactAssignment'
)
clone_fields = (
'group', 'description',
)

View File

@ -6,6 +6,7 @@ from django.utils.translation import gettext_lazy as _
from dcim.models import Device
from netbox.models import OrganizationalModel, PrimaryModel
from netbox.models.features import ContactsMixin
from virtualization.choices import *
__all__ = (
@ -28,20 +29,16 @@ class ClusterType(OrganizationalModel):
return reverse('virtualization:clustertype', args=[self.pk])
class ClusterGroup(OrganizationalModel):
class ClusterGroup(ContactsMixin, OrganizationalModel):
"""
An organizational group of Clusters.
"""
# Generic relations
vlan_groups = GenericRelation(
to='ipam.VLANGroup',
content_type_field='scope_type',
object_id_field='scope_id',
related_query_name='cluster_group'
)
contacts = GenericRelation(
to='tenancy.ContactAssignment'
)
class Meta:
ordering = ('name',)
@ -52,7 +49,7 @@ class ClusterGroup(OrganizationalModel):
return reverse('virtualization:clustergroup', args=[self.pk])
class Cluster(PrimaryModel):
class Cluster(ContactsMixin, PrimaryModel):
"""
A cluster of VirtualMachines. Each Cluster may optionally be associated with one or more Devices.
"""
@ -101,9 +98,6 @@ class Cluster(PrimaryModel):
object_id_field='scope_id',
related_query_name='cluster'
)
contacts = GenericRelation(
to='tenancy.ContactAssignment'
)
clone_fields = (
'type', 'group', 'status', 'tenant', 'site',

View File

@ -12,6 +12,7 @@ from extras.models import ConfigContextModel
from extras.querysets import ConfigContextModelQuerySet
from netbox.config import get_config
from netbox.models import NetBoxModel, PrimaryModel
from netbox.models.features import ContactsMixin
from utilities.fields import CounterCacheField, NaturalOrderingField
from utilities.ordering import naturalize_interface
from utilities.query_functions import CollateAsChar
@ -24,7 +25,7 @@ __all__ = (
)
class VirtualMachine(PrimaryModel, ConfigContextModel):
class VirtualMachine(ContactsMixin, PrimaryModel, ConfigContextModel):
"""
A virtual machine which runs inside a Cluster.
"""
@ -129,11 +130,6 @@ class VirtualMachine(PrimaryModel, ConfigContextModel):
to_field='virtual_machine'
)
# Generic relation
contacts = GenericRelation(
to='tenancy.ContactAssignment'
)
objects = ConfigContextModelQuerySet.as_manager()
clone_fields = (