mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-23 04:22:01 -06:00
Introduce ContactsMixin
This commit is contained in:
parent
14e23c3d00
commit
2afce6c94b
@ -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',
|
||||
|
@ -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:
|
||||
|
@ -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 = (
|
||||
|
@ -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',
|
||||
)
|
||||
|
@ -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',
|
||||
|
@ -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 = (
|
||||
|
@ -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',)
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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',
|
||||
)
|
||||
|
@ -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',
|
||||
|
@ -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 = (
|
||||
|
Loading…
Reference in New Issue
Block a user