mirror of
https://github.com/netbox-community/netbox.git
synced 2025-08-08 00:28:16 -06:00
Enable MPTT for module bays
This commit is contained in:
parent
f8d99ffe5e
commit
6372d065be
@ -496,12 +496,18 @@ class ModuleType(NetBoxObjectType):
|
||||
|
||||
@strawberry_django.type(
|
||||
models.ModuleBay,
|
||||
fields='__all__',
|
||||
# fields='__all__',
|
||||
exclude=('parent',),
|
||||
filters=ModuleBayFilter
|
||||
)
|
||||
class ModuleBayType(ModularComponentType):
|
||||
|
||||
installed_module: Annotated["ModuleType", strawberry.lazy('dcim.graphql.types')] | None
|
||||
children: List[Annotated["ModuleBayType", strawberry.lazy('dcim.graphql.types')]]
|
||||
|
||||
@strawberry_django.field
|
||||
def parent(self) -> Annotated["ModuleBayType", strawberry.lazy('dcim.graphql.types')] | None:
|
||||
return self.parent
|
||||
|
||||
|
||||
@strawberry_django.type(
|
||||
|
44
netbox/dcim/migrations/0191_modulebay_mptt.py
Normal file
44
netbox/dcim/migrations/0191_modulebay_mptt.py
Normal file
@ -0,0 +1,44 @@
|
||||
# Generated by Django 5.0.7 on 2024-08-02 20:07
|
||||
|
||||
import django.db.models.deletion
|
||||
import mptt.fields
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('dcim', '0190_nested_modules'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='modulebay',
|
||||
name='level',
|
||||
field=models.PositiveIntegerField(default=0, editable=False),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='modulebay',
|
||||
name='lft',
|
||||
field=models.PositiveIntegerField(default=0, editable=False),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='modulebay',
|
||||
name='parent',
|
||||
field=mptt.fields.TreeForeignKey(blank=True, editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='children', to='dcim.modulebay'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='modulebay',
|
||||
name='rght',
|
||||
field=models.PositiveIntegerField(default=0, editable=False),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='modulebay',
|
||||
name='tree_id',
|
||||
field=models.PositiveIntegerField(db_index=True, default=0, editable=False),
|
||||
preserve_default=False,
|
||||
),
|
||||
]
|
@ -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(ModularComponentModel, 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,6 +1107,8 @@ class ModuleBay(ModularComponentModel, TrackingModelMixin):
|
||||
help_text=_('Identifier to reference when renaming installed components')
|
||||
)
|
||||
|
||||
objects = TreeManager()
|
||||
|
||||
clone_fields = ('device',)
|
||||
|
||||
class Meta(ModularComponentModel.Meta):
|
||||
@ -1110,6 +1121,9 @@ class ModuleBay(ModularComponentModel, TrackingModelMixin):
|
||||
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})
|
||||
|
||||
@ -1127,6 +1141,11 @@ class ModuleBay(ModularComponentModel, TrackingModelMixin):
|
||||
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):
|
||||
"""
|
||||
|
@ -1046,7 +1046,8 @@ class Device(
|
||||
self._instantiate_components(self.device_type.interfacetemplates.all())
|
||||
self._instantiate_components(self.device_type.rearporttemplates.all())
|
||||
self._instantiate_components(self.device_type.frontporttemplates.all())
|
||||
self._instantiate_components(self.device_type.modulebaytemplates.all())
|
||||
# Disable bulk_create to accommodate MPTT
|
||||
self._instantiate_components(self.device_type.modulebaytemplates.all(), bulk_create=False)
|
||||
self._instantiate_components(self.device_type.devicebaytemplates.all())
|
||||
# Disable bulk_create to accommodate MPTT
|
||||
self._instantiate_components(self.device_type.inventoryitemtemplates.all(), bulk_create=False)
|
||||
@ -1269,17 +1270,19 @@ class Module(PrimaryModel, ConfigContextModel):
|
||||
if not disable_replication:
|
||||
create_instances.append(template_instance)
|
||||
|
||||
component_model.objects.bulk_create(create_instances)
|
||||
# Emit the post_save signal for each newly created object
|
||||
for component in create_instances:
|
||||
post_save.send(
|
||||
sender=component_model,
|
||||
instance=component,
|
||||
created=True,
|
||||
raw=False,
|
||||
using='default',
|
||||
update_fields=None
|
||||
)
|
||||
# component_model.objects.bulk_create(create_instances)
|
||||
# # Emit the post_save signal for each newly created object
|
||||
# for component in create_instances:
|
||||
# post_save.send(
|
||||
# sender=component_model,
|
||||
# instance=component,
|
||||
# created=True,
|
||||
# raw=False,
|
||||
# using='default',
|
||||
# update_fields=None
|
||||
# )
|
||||
for instance in create_instances:
|
||||
instance.save()
|
||||
|
||||
update_fields = ['module']
|
||||
component_model.objects.bulk_update(update_instances, update_fields)
|
||||
|
@ -313,6 +313,10 @@ class ModularDeviceComponentTable(DeviceComponentTable):
|
||||
verbose_name=_('Inventory Items'),
|
||||
)
|
||||
|
||||
class Meta(NetBoxTable.Meta):
|
||||
pass
|
||||
# order_by = ('device', 'module', 'name')
|
||||
|
||||
|
||||
class CableTerminationTable(NetBoxTable):
|
||||
cable = tables.Column(
|
||||
@ -852,10 +856,9 @@ class ModuleBayTable(ModularDeviceComponentTable):
|
||||
'args': [Accessor('device_id')],
|
||||
}
|
||||
)
|
||||
parent_bay = tables.Column(
|
||||
accessor=tables.A('module__module_bay'),
|
||||
parent = tables.Column(
|
||||
linkify=True,
|
||||
verbose_name=_('Parent Bay')
|
||||
verbose_name=_('Parent'),
|
||||
)
|
||||
installed_module = tables.Column(
|
||||
linkify=True,
|
||||
@ -878,14 +881,14 @@ class ModuleBayTable(ModularDeviceComponentTable):
|
||||
verbose_name=_('Module Status')
|
||||
)
|
||||
|
||||
class Meta(DeviceComponentTable.Meta):
|
||||
class Meta(ModularDeviceComponentTable.Meta):
|
||||
model = models.ModuleBay
|
||||
fields = (
|
||||
'pk', 'id', 'name', 'device', 'parent_bay', 'label', 'position', 'installed_module', 'module_status',
|
||||
'pk', 'id', 'name', 'device', 'parent', 'label', 'position', 'installed_module', 'module_status',
|
||||
'module_serial', 'module_asset_tag', 'description', 'tags',
|
||||
)
|
||||
default_columns = (
|
||||
'pk', 'name', 'device', 'parent_bay', 'label', 'installed_module', 'module_status', 'description',
|
||||
'pk', 'name', 'device', 'parent', 'label', 'installed_module', 'module_status', 'description',
|
||||
)
|
||||
|
||||
def render_parent_bay(self, value):
|
||||
@ -896,17 +899,24 @@ class ModuleBayTable(ModularDeviceComponentTable):
|
||||
|
||||
|
||||
class DeviceModuleBayTable(ModuleBayTable):
|
||||
name = tables.TemplateColumn(
|
||||
verbose_name=_('Name'),
|
||||
template_code='<a href="{{ record.get_absolute_url }}" style="padding-left: {{ record.level }}0px">'
|
||||
'{{ value }}</a>',
|
||||
order_by=Accessor('_name'),
|
||||
attrs={'td': {'class': 'text-nowrap'}}
|
||||
)
|
||||
actions = columns.ActionsColumn(
|
||||
extra_buttons=MODULEBAY_BUTTONS
|
||||
)
|
||||
|
||||
class Meta(DeviceComponentTable.Meta):
|
||||
class Meta(ModuleBayTable.Meta):
|
||||
model = models.ModuleBay
|
||||
fields = (
|
||||
'pk', 'id', 'parent_bay', 'name', 'label', 'position', 'installed_module', 'module_status', 'module_serial',
|
||||
'pk', 'id', 'parent', 'name', 'label', 'position', 'installed_module', 'module_status', 'module_serial',
|
||||
'module_asset_tag', 'description', 'tags', 'actions',
|
||||
)
|
||||
default_columns = ('pk', 'parent_bay', 'name', 'label', 'installed_module', 'module_status', 'description')
|
||||
default_columns = ('pk', 'name', 'label', 'installed_module', 'module_status', 'description')
|
||||
|
||||
|
||||
class InventoryItemTable(DeviceComponentTable):
|
||||
|
Loading…
Reference in New Issue
Block a user