mirror of
https://github.com/netbox-community/netbox.git
synced 2026-01-15 00:02:17 -06:00
* 10500 add ModularComponentModel * 10500 add ModularComponentModel * 10500 add to forms * 10500 add to serializer, tables * 10500 template * 10500 add docs * 10500 check recursion * 10500 fix graphql * 10500 fix conflicting migration from merge * 10500 token resolution * 10500 don't return reverse * 10500 don't return reverse / optimize * Add ModuleTypeModuleBaysView * Fix replication of module bays on new modules * Clean up tables & templates * Adjust uniqueness constraints * Correct URL * Clean up docs * Fix up serializers * 10500 add filterset tests * 10500 add nested validation to Module * Misc cleanup * 10500 ModuleBay recursion Test * 10500 ModuleBay recursion Test * 10500 ModuleBay recursion Test * 10500 ModuleBay recursion Test * Enable MPTT for module bays * Fix tests * Fix validation of module token in component names * Misc cleanup * Merge migrations * Fix table ordering --------- Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
This commit is contained in:
@@ -4,7 +4,7 @@ from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelatio
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.core.validators import MaxValueValidator, MinValueValidator
|
||||
from django.db import models
|
||||
from django.db.models import Sum
|
||||
from django.db.models import F, Sum
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from mptt.models import MPTTModel, TreeForeignKey
|
||||
@@ -1087,10 +1087,19 @@ class RearPort(ModularComponentModel, CabledObjectModel, TrackingModelMixin):
|
||||
# Bays
|
||||
#
|
||||
|
||||
class ModuleBay(ComponentModel, TrackingModelMixin):
|
||||
class ModuleBay(ModularComponentModel, TrackingModelMixin, MPTTModel):
|
||||
"""
|
||||
An empty space within a Device which can house a child device
|
||||
"""
|
||||
parent = TreeForeignKey(
|
||||
to='self',
|
||||
on_delete=models.CASCADE,
|
||||
related_name='children',
|
||||
blank=True,
|
||||
null=True,
|
||||
editable=False,
|
||||
db_index=True
|
||||
)
|
||||
position = models.CharField(
|
||||
verbose_name=_('position'),
|
||||
max_length=30,
|
||||
@@ -1098,15 +1107,45 @@ class ModuleBay(ComponentModel, TrackingModelMixin):
|
||||
help_text=_('Identifier to reference when renaming installed components')
|
||||
)
|
||||
|
||||
objects = TreeManager()
|
||||
|
||||
clone_fields = ('device',)
|
||||
|
||||
class Meta(ComponentModel.Meta):
|
||||
class Meta(ModularComponentModel.Meta):
|
||||
constraints = (
|
||||
models.UniqueConstraint(
|
||||
fields=('device', 'module', 'name'),
|
||||
name='%(app_label)s_%(class)s_unique_device_module_name'
|
||||
),
|
||||
)
|
||||
verbose_name = _('module bay')
|
||||
verbose_name_plural = _('module bays')
|
||||
|
||||
class MPTTMeta:
|
||||
order_insertion_by = ('module',)
|
||||
|
||||
def get_absolute_url(self):
|
||||
return reverse('dcim:modulebay', kwargs={'pk': self.pk})
|
||||
|
||||
def clean(self):
|
||||
super().clean()
|
||||
|
||||
# Check for recursion
|
||||
if module := self.module:
|
||||
module_bays = [self.pk]
|
||||
modules = []
|
||||
while module:
|
||||
if module.pk in modules or module.module_bay.pk in module_bays:
|
||||
raise ValidationError(_("A module bay cannot belong to a module installed within it."))
|
||||
modules.append(module.pk)
|
||||
module_bays.append(module.module_bay.pk)
|
||||
module = module.module_bay.module if module.module_bay else None
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
if self.module:
|
||||
self.parent = self.module.module_bay
|
||||
super().save(*args, **kwargs)
|
||||
|
||||
|
||||
class DeviceBay(ComponentModel, TrackingModelMixin):
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user