Przeglądaj źródła

Introduce ImageAttachmentsMixin

Jeremy Stretch 2 lat temu
rodzic
commit
14e23c3d00

+ 3 - 7
netbox/circuits/models/circuits.py

@@ -6,9 +6,8 @@ from django.utils.translation import gettext_lazy as _
 
 from circuits.choices import *
 from dcim.models import CabledObjectModel
-from netbox.models import (
-    ChangeLoggedModel, CustomFieldsMixin, CustomLinksMixin, OrganizationalModel, PrimaryModel, TagsMixin,
-)
+from netbox.models import ChangeLoggedModel, OrganizationalModel, PrimaryModel
+from netbox.models.features import CustomFieldsMixin, CustomLinksMixin, ImageAttachmentsMixin, TagsMixin
 
 __all__ = (
     'Circuit',
@@ -31,7 +30,7 @@ class CircuitType(OrganizationalModel):
         verbose_name_plural = _('circuit types')
 
 
-class Circuit(PrimaryModel):
+class Circuit(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
@@ -93,9 +92,6 @@ class Circuit(PrimaryModel):
     contacts = GenericRelation(
         to='tenancy.ContactAssignment'
     )
-    images = GenericRelation(
-        to='extras.ImageAttachment'
-    )
 
     # Cache associated CircuitTerminations
     termination_a = models.ForeignKey(

+ 4 - 15
netbox/dcim/models/devices.py

@@ -20,6 +20,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 utilities.choices import ColorChoices
 from utilities.fields import ColorField, CounterCacheField, NaturalOrderingField
 from utilities.tracking import TrackingModelMixin
@@ -62,7 +63,7 @@ class Manufacturer(OrganizationalModel):
         return reverse('dcim:manufacturer', args=[self.pk])
 
 
-class DeviceType(PrimaryModel, WeightMixin):
+class DeviceType(ImageAttachmentsMixin, PrimaryModel, WeightMixin):
     """
     A DeviceType represents a particular make (Manufacturer) and model of device. It specifies rack height and depth, as
     well as high-level functional role(s).
@@ -180,10 +181,6 @@ class DeviceType(PrimaryModel, WeightMixin):
         to_field='device_type'
     )
 
-    images = GenericRelation(
-        to='extras.ImageAttachment'
-    )
-
     clone_fields = (
         'manufacturer', 'default_platform', 'u_height', 'is_full_depth', 'subdevice_role', 'airflow', 'weight',
         'weight_unit',
@@ -366,7 +363,7 @@ class DeviceType(PrimaryModel, WeightMixin):
         return self.subdevice_role == SubdeviceRoleChoices.ROLE_CHILD
 
 
-class ModuleType(PrimaryModel, WeightMixin):
+class ModuleType(ImageAttachmentsMixin, PrimaryModel, WeightMixin):
     """
     A ModuleType represents a hardware element that can be installed within a device and which houses additional
     components; for example, a line card within a chassis-based switch such as the Cisco Catalyst 6500. Like a
@@ -389,11 +386,6 @@ class ModuleType(PrimaryModel, WeightMixin):
         help_text=_('Discrete part number (optional)')
     )
 
-    # Generic relations
-    images = GenericRelation(
-        to='extras.ImageAttachment'
-    )
-
     clone_fields = ('manufacturer', 'weight', 'weight_unit',)
     prerequisite_models = (
         'dcim.Manufacturer',
@@ -539,7 +531,7 @@ def update_interface_bridges(device, interface_templates, module=None):
             interface.save()
 
 
-class Device(PrimaryModel, ConfigContextModel, TrackingModelMixin):
+class Device(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.
@@ -770,9 +762,6 @@ class Device(PrimaryModel, ConfigContextModel, TrackingModelMixin):
     contacts = GenericRelation(
         to='tenancy.ContactAssignment'
     )
-    images = GenericRelation(
-        to='extras.ImageAttachment'
-    )
 
     objects = ConfigContextModelQuerySet.as_manager()
 

+ 2 - 4
netbox/dcim/models/power.py

@@ -8,6 +8,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 utilities.validators import ExclusionValidator
 from .device_components import CabledObjectModel, PathEndpoint
 
@@ -21,7 +22,7 @@ __all__ = (
 # Power
 #
 
-class PowerPanel(PrimaryModel):
+class PowerPanel(ImageAttachmentsMixin, PrimaryModel):
     """
     A distribution point for electrical power; e.g. a data center RPP.
     """
@@ -44,9 +45,6 @@ class PowerPanel(PrimaryModel):
     contacts = GenericRelation(
         to='tenancy.ContactAssignment'
     )
-    images = GenericRelation(
-        to='extras.ImageAttachment'
-    )
 
     prerequisite_models = (
         'dcim.Site',

+ 2 - 4
netbox/dcim/models/racks.py

@@ -15,6 +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 utilities.choices import ColorChoices
 from utilities.fields import ColorField, NaturalOrderingField
 from utilities.utils import array_to_string, drange, to_grams
@@ -52,7 +53,7 @@ class RackRole(OrganizationalModel):
         return reverse('dcim:rackrole', args=[self.pk])
 
 
-class Rack(PrimaryModel, WeightMixin):
+class Rack(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.
@@ -196,9 +197,6 @@ class Rack(PrimaryModel, WeightMixin):
     contacts = GenericRelation(
         to='tenancy.ContactAssignment'
     )
-    images = GenericRelation(
-        to='extras.ImageAttachment'
-    )
 
     clone_fields = (
         'site', 'location', 'tenant', 'status', 'role', 'type', 'width', 'u_height', 'desc_units', 'outer_width',

+ 3 - 8
netbox/dcim/models/sites.py

@@ -8,6 +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 utilities.fields import NaturalOrderingField
 
 __all__ = (
@@ -136,7 +137,7 @@ class SiteGroup(NestedGroupModel):
 # Sites
 #
 
-class Site(PrimaryModel):
+class Site(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).
@@ -237,9 +238,6 @@ class Site(PrimaryModel):
     contacts = GenericRelation(
         to='tenancy.ContactAssignment'
     )
-    images = GenericRelation(
-        to='extras.ImageAttachment'
-    )
 
     clone_fields = (
         'status', 'region', 'group', 'tenant', 'facility', 'time_zone', 'physical_address', 'shipping_address',
@@ -265,7 +263,7 @@ class Site(PrimaryModel):
 # Locations
 #
 
-class Location(NestedGroupModel):
+class Location(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.
@@ -299,9 +297,6 @@ class Location(NestedGroupModel):
     contacts = GenericRelation(
         to='tenancy.ContactAssignment'
     )
-    images = GenericRelation(
-        to='extras.ImageAttachment'
-    )
 
     clone_fields = ('site', 'parent', 'status', 'tenant', 'description')
     prerequisite_models = (

+ 13 - 0
netbox/netbox/models/features.py

@@ -29,6 +29,7 @@ __all__ = (
     'CustomLinksMixin',
     'CustomValidationMixin',
     'ExportTemplatesMixin',
+    'ImageAttachmentsMixin',
     'JobsMixin',
     'JournalingMixin',
     'SyncedDataMixin',
@@ -307,6 +308,18 @@ class ExportTemplatesMixin(models.Model):
         abstract = True
 
 
+class ImageAttachmentsMixin(models.Model):
+    """
+    Enables the assignments of ImageAttachments.
+    """
+    images = GenericRelation(
+        to='extras.ImageAttachment'
+    )
+
+    class Meta:
+        abstract = True
+
+
 class BookmarksMixin(models.Model):
     """
     Enables support for user bookmarks.