Refactor PortAssignment and PortAssignmentTemplate into PortAssignmentBase

This commit is contained in:
Jeremy Stretch
2025-11-20 15:43:18 -05:00
parent f067122ccd
commit 1e0748e618
4 changed files with 64 additions and 84 deletions

View File

@@ -68,8 +68,6 @@ class Migration(migrations.Migration):
( (
'front_port_position', 'front_port_position',
models.PositiveSmallIntegerField( models.PositiveSmallIntegerField(
blank=True,
null=True,
validators=[ validators=[
django.core.validators.MinValueValidator(1), django.core.validators.MinValueValidator(1),
django.core.validators.MaxValueValidator(1024) django.core.validators.MaxValueValidator(1024)
@@ -129,8 +127,6 @@ class Migration(migrations.Migration):
( (
'front_port_position', 'front_port_position',
models.PositiveSmallIntegerField( models.PositiveSmallIntegerField(
blank=True,
null=True,
validators=[ validators=[
django.core.validators.MinValueValidator(1), django.core.validators.MinValueValidator(1),
django.core.validators.MaxValueValidator(1024) django.core.validators.MaxValueValidator(1024)

View File

@@ -0,0 +1,57 @@
from django.core.exceptions import ValidationError
from django.core.validators import MaxValueValidator, MinValueValidator
from django.db import models
from django.utils.translation import gettext_lazy as _
from dcim.constants import PORT_POSITION_MAX, PORT_POSITION_MIN
__all__ = (
'PortAssignmentBase',
)
class PortAssignmentBase(models.Model):
"""
Base class for PortAssignment and PortAssignment Template
"""
front_port_position = models.PositiveSmallIntegerField(
validators=(
MinValueValidator(PORT_POSITION_MIN),
MaxValueValidator(PORT_POSITION_MAX),
),
)
rear_port_position = models.PositiveSmallIntegerField(
validators=(
MinValueValidator(PORT_POSITION_MIN),
MaxValueValidator(PORT_POSITION_MAX),
),
)
class Meta:
abstract = True
constraints = (
models.UniqueConstraint(
fields=('front_port', 'front_port_position'),
name='%(app_label)s_%(class)s_unique_front_port_position'
),
models.UniqueConstraint(
fields=('rear_port', 'rear_port_position'),
name='%(app_label)s_%(class)s_unique_rear_port_position'
),
)
def clean(self):
super().clean()
# Validate rear port position assignment
if self.rear_port_position > self.rear_port.positions:
raise ValidationError({
"rear_port_position": _(
"Invalid rear port position ({rear_port_position}): Rear port {name} has only {positions} "
"positions."
).format(
rear_port_position=self.rear_port_position,
name=self.rear_port.name,
positions=self.rear_port.positions
)
})

View File

@@ -7,6 +7,7 @@ from mptt.models import MPTTModel, TreeForeignKey
from dcim.choices import * from dcim.choices import *
from dcim.constants import * from dcim.constants import *
from dcim.models.base import PortAssignmentBase
from dcim.models.mixins import InterfaceValidationMixin from dcim.models.mixins import InterfaceValidationMixin
from netbox.models import ChangeLoggedModel from netbox.models import ChangeLoggedModel
from utilities.fields import ColorField, NaturalOrderingField from utilities.fields import ColorField, NaturalOrderingField
@@ -28,6 +29,7 @@ __all__ = (
'InterfaceTemplate', 'InterfaceTemplate',
'InventoryItemTemplate', 'InventoryItemTemplate',
'ModuleBayTemplate', 'ModuleBayTemplate',
'PortAssignmentTemplate',
'PowerOutletTemplate', 'PowerOutletTemplate',
'PowerPortTemplate', 'PowerPortTemplate',
'RearPortTemplate', 'RearPortTemplate',
@@ -518,7 +520,7 @@ class InterfaceTemplate(InterfaceValidationMixin, ModularComponentTemplateModel)
} }
class PortAssignmentTemplate(models.Model): class PortAssignmentTemplate(PortAssignmentBase):
""" """
Maps a FrontPortTemplate & position to a RearPortTemplate & position. Maps a FrontPortTemplate & position to a RearPortTemplate & position.
""" """
@@ -526,38 +528,13 @@ class PortAssignmentTemplate(models.Model):
to='dcim.FrontPortTemplate', to='dcim.FrontPortTemplate',
on_delete=models.CASCADE, on_delete=models.CASCADE,
) )
front_port_position = models.PositiveSmallIntegerField(
blank=True,
null=True,
validators=(
MinValueValidator(PORT_POSITION_MIN),
MaxValueValidator(PORT_POSITION_MAX),
),
)
rear_port = models.ForeignKey( rear_port = models.ForeignKey(
to='dcim.RearPortTemplate', to='dcim.RearPortTemplate',
on_delete=models.CASCADE, on_delete=models.CASCADE,
) )
rear_port_position = models.PositiveSmallIntegerField(
validators=(
MinValueValidator(PORT_POSITION_MIN),
MaxValueValidator(PORT_POSITION_MAX),
),
)
class Meta:
constraints = (
models.UniqueConstraint(
fields=('front_port', 'front_port_position'),
name='%(app_label)s_%(class)s_unique_front_port_position'
),
models.UniqueConstraint(
fields=('rear_port', 'rear_port_position'),
name='%(app_label)s_%(class)s_unique_rear_port_position'
),
)
def clean(self): def clean(self):
super().clean()
# Validate rear port assignment # Validate rear port assignment
if self.front_port.device_type_id != self.rear_port.device_type_id: if self.front_port.device_type_id != self.rear_port.device_type_id:
@@ -567,19 +544,6 @@ class PortAssignmentTemplate(models.Model):
) )
}) })
# Validate rear port position assignment
if self.rear_port_position > self.rear_port.positions:
raise ValidationError({
"rear_port_position": _(
"Invalid rear port position ({rear_port_position}): Rear port {name} has only {positions} "
"positions."
).format(
rear_port_position=self.rear_port_position,
name=self.rear_port.name,
positions=self.rear_port.positions
)
})
class FrontPortTemplate(ModularComponentTemplateModel): class FrontPortTemplate(ModularComponentTemplateModel):
""" """

View File

@@ -11,6 +11,7 @@ from mptt.models import MPTTModel, TreeForeignKey
from dcim.choices import * from dcim.choices import *
from dcim.constants import * from dcim.constants import *
from dcim.fields import WWNField from dcim.fields import WWNField
from dcim.models.base import PortAssignmentBase
from dcim.models.mixins import InterfaceValidationMixin from dcim.models.mixins import InterfaceValidationMixin
from netbox.choices import ColorChoices from netbox.choices import ColorChoices
from netbox.models import OrganizationalModel, NetBoxModel from netbox.models import OrganizationalModel, NetBoxModel
@@ -1070,7 +1071,7 @@ class Interface(
# Pass-through ports # Pass-through ports
# #
class PortAssignment(models.Model): class PortAssignment(PortAssignmentBase):
""" """
Maps a FrontPort & position to a RearPort & position. Maps a FrontPort & position to a RearPort & position.
""" """
@@ -1078,38 +1079,13 @@ class PortAssignment(models.Model):
to='dcim.FrontPort', to='dcim.FrontPort',
on_delete=models.CASCADE, on_delete=models.CASCADE,
) )
front_port_position = models.PositiveSmallIntegerField(
blank=True,
null=True,
validators=(
MinValueValidator(PORT_POSITION_MIN),
MaxValueValidator(PORT_POSITION_MAX),
),
)
rear_port = models.ForeignKey( rear_port = models.ForeignKey(
to='dcim.RearPort', to='dcim.RearPort',
on_delete=models.CASCADE, on_delete=models.CASCADE,
) )
rear_port_position = models.PositiveSmallIntegerField(
validators=(
MinValueValidator(PORT_POSITION_MIN),
MaxValueValidator(PORT_POSITION_MAX),
),
)
class Meta:
constraints = (
models.UniqueConstraint(
fields=('front_port', 'front_port_position'),
name='%(app_label)s_%(class)s_unique_front_port_position'
),
models.UniqueConstraint(
fields=('rear_port', 'rear_port_position'),
name='%(app_label)s_%(class)s_unique_rear_port_position'
),
)
def clean(self): def clean(self):
super().clean()
# Validate rear port assignment # Validate rear port assignment
if self.front_port.device_id != self.rear_port.device_id: if self.front_port.device_id != self.rear_port.device_id:
@@ -1119,19 +1095,6 @@ class PortAssignment(models.Model):
) )
}) })
# Validate rear port position assignment
if self.rear_port_position > self.rear_port.positions:
raise ValidationError({
"rear_port_position": _(
"Invalid rear port position ({rear_port_position}): Rear port {name} has only {positions} "
"positions."
).format(
rear_port_position=self.rear_port_position,
name=self.rear_port.name,
positions=self.rear_port.positions
)
})
class FrontPort(ModularComponentModel, CabledObjectModel, TrackingModelMixin): class FrontPort(ModularComponentModel, CabledObjectModel, TrackingModelMixin):
""" """