diff --git a/netbox/ipam/migrations/0071_vlantranslationpolicy_vlantranslationrule.py b/netbox/ipam/migrations/0071_vlantranslationpolicy_vlantranslationrule.py index aa3ed137d..c8a57ef44 100644 --- a/netbox/ipam/migrations/0071_vlantranslationpolicy_vlantranslationrule.py +++ b/netbox/ipam/migrations/0071_vlantranslationpolicy_vlantranslationrule.py @@ -1,5 +1,6 @@ # Generated by Django 5.0.9 on 2024-10-11 19:45 +import django.core.validators import django.db.models.deletion import taggit.managers import utilities.json @@ -39,8 +40,8 @@ class Migration(migrations.Migration): ('created', models.DateTimeField(auto_now_add=True, null=True)), ('last_updated', models.DateTimeField(auto_now=True, null=True)), ('custom_field_data', models.JSONField(blank=True, default=dict, encoder=utilities.json.CustomFieldJSONEncoder)), - ('local_vid', models.IntegerField()), - ('remote_vid', models.IntegerField()), + ('local_vid', models.PositiveSmallIntegerField(validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(4094)])), + ('remote_vid', models.PositiveSmallIntegerField(validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(4094)])), ('policy', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='rules', to='ipam.vlantranslationpolicy')), ('tags', taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag')), ], @@ -49,4 +50,12 @@ class Migration(migrations.Migration): 'ordering': ('policy', 'local_vid', 'remote_vid'), }, ), + migrations.AddConstraint( + model_name='vlantranslationrule', + constraint=models.UniqueConstraint(fields=('policy', 'local_vid'), name='ipam_vlantranslationrule_unique_policy_local_vid'), + ), + migrations.AddConstraint( + model_name='vlantranslationrule', + constraint=models.UniqueConstraint(fields=('policy', 'remote_vid'), name='ipam_vlantranslationrule_unique_policy_remote_vid'), + ), ] diff --git a/netbox/ipam/models/vlans.py b/netbox/ipam/models/vlans.py index 638647cbb..ffae0a2ed 100644 --- a/netbox/ipam/models/vlans.py +++ b/netbox/ipam/models/vlans.py @@ -283,11 +283,6 @@ class VLANTranslationPolicy(PrimaryModel): max_length=100, unique=True, ) - description = models.CharField( - verbose_name=_('description'), - max_length=200, - blank=True, - ) class Meta: verbose_name = _('VLAN translation policy') @@ -304,23 +299,41 @@ class VLANTranslationRule(NetBoxModel): related_name='rules', on_delete=models.CASCADE, ) - local_vid = models.IntegerField() - remote_vid = models.IntegerField() + local_vid = models.PositiveSmallIntegerField( + verbose_name=_('Local VLAN ID'), + validators=( + MinValueValidator(VLAN_VID_MIN), + MaxValueValidator(VLAN_VID_MAX) + ), + help_text=_("Numeric VLAN ID (1-4094)") + ) + remote_vid = models.PositiveSmallIntegerField( + verbose_name=_('Remote VLAN ID'), + validators=( + MinValueValidator(VLAN_VID_MIN), + MaxValueValidator(VLAN_VID_MAX) + ), + help_text=_("Numeric VLAN ID (1-4094)") + ) class Meta: verbose_name = _('VLAN translation rule') ordering = ('policy', 'local_vid', 'remote_vid',) - # Unique constraints are TBD - # constraints = ( - # models.UniqueConstraint( - # fields=('policy', 'local_vid'), - # name='%(app_label)s_%(class)s_unique_policy_local_vid' - # ), - # models.UniqueConstraint( - # fields=('policy', 'remote_vid'), - # name='%(app_label)s_%(class)s_unique_policy_remote_vid' - # ), - # ) + constraints = ( + models.UniqueConstraint( + fields=('policy', 'local_vid'), + name='%(app_label)s_%(class)s_unique_policy_local_vid' + ), + models.UniqueConstraint( + fields=('policy', 'remote_vid'), + name='%(app_label)s_%(class)s_unique_policy_remote_vid' + ), + ) def __str__(self): return f'{self.local_vid} -> {self.remote_vid} ({self.policy})' + + def to_objectchange(self, action): + objectchange = super().to_objectchange(action) + objectchange.related_object = self.policy + return objectchange