Closes #21016: Add missing MPTT tree indexes (#21432)

Upgrade django-mptt to 0.18.0 and add empty indexes tuple to MPTT model
Meta classes. The empty tuple triggers Django's migration detection for
indexes that django-mptt adds dynamically (see
django-mptt/django-mptt#682). We cannot define the indexes explicitly
because the MPTT fields don't exist when the Meta class is evaluated.

Affected models: Region, SiteGroup, Location, DeviceRole, Platform,
ModuleBay, InventoryItem, InventoryItemTemplate, TenantGroup,
ContactGroup, WirelessLANGroup
This commit is contained in:
Jason Novinger
2026-02-13 10:00:04 -06:00
committed by GitHub
parent 1190adde2b
commit 0b7375136d
11 changed files with 123 additions and 1 deletions

View File

@@ -0,0 +1,49 @@
# Generated by Django 5.2.10 on 2026-02-13 13:36
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('contenttypes', '0002_remove_content_type_name'),
('dcim', '0225_gfk_indexes'),
('extras', '0134_owner'),
('tenancy', '0022_add_comments_to_organizationalmodel'),
('users', '0015_owner'),
]
operations = [
migrations.AddIndex(
model_name='devicerole',
index=models.Index(fields=['tree_id', 'lft'], name='dcim_devicerole_tree_id_lfbf11'),
),
migrations.AddIndex(
model_name='inventoryitem',
index=models.Index(fields=['tree_id', 'lft'], name='dcim_inventoryitem_tree_id975c'),
),
migrations.AddIndex(
model_name='inventoryitemtemplate',
index=models.Index(fields=['tree_id', 'lft'], name='dcim_inventoryitemtemplatedee0'),
),
migrations.AddIndex(
model_name='location',
index=models.Index(fields=['tree_id', 'lft'], name='dcim_location_tree_id_lft_idx'),
),
migrations.AddIndex(
model_name='modulebay',
index=models.Index(fields=['tree_id', 'lft'], name='dcim_modulebay_tree_id_lft_idx'),
),
migrations.AddIndex(
model_name='platform',
index=models.Index(fields=['tree_id', 'lft'], name='dcim_platform_tree_id_lft_idx'),
),
migrations.AddIndex(
model_name='region',
index=models.Index(fields=['tree_id', 'lft'], name='dcim_region_tree_id_lft_idx'),
),
migrations.AddIndex(
model_name='sitegroup',
index=models.Index(fields=['tree_id', 'lft'], name='dcim_sitegroup_tree_id_lft_idx'),
),
]

View File

@@ -1263,6 +1263,9 @@ class ModuleBay(ModularComponentModel, TrackingModelMixin, MPTTModel):
clone_fields = ('device',)
class Meta(ModularComponentModel.Meta):
# Empty tuple triggers Django migration detection for MPTT indexes
# (see #21016, django-mptt/django-mptt#682)
indexes = ()
constraints = (
models.UniqueConstraint(
fields=('device', 'module', 'name'),

View File

@@ -401,6 +401,9 @@ class DeviceRole(NestedGroupModel):
class Meta:
ordering = ('name',)
# Empty tuple triggers Django migration detection for MPTT indexes
# (see #21016, django-mptt/django-mptt#682)
indexes = ()
constraints = (
models.UniqueConstraint(
fields=('parent', 'name'),
@@ -452,6 +455,9 @@ class Platform(NestedGroupModel):
class Meta:
ordering = ('name',)
# Empty tuple triggers Django migration detection for MPTT indexes
# (see #21016, django-mptt/django-mptt#682)
indexes = ()
verbose_name = _('platform')
verbose_name_plural = _('platforms')
constraints = (

View File

@@ -44,6 +44,9 @@ class Region(ContactsMixin, NestedGroupModel):
)
class Meta:
# Empty tuple triggers Django migration detection for MPTT indexes
# (see #21016, django-mptt/django-mptt#682)
indexes = ()
constraints = (
models.UniqueConstraint(
fields=('parent', 'name'),
@@ -100,6 +103,9 @@ class SiteGroup(ContactsMixin, NestedGroupModel):
)
class Meta:
# Empty tuple triggers Django migration detection for MPTT indexes
# (see #21016, django-mptt/django-mptt#682)
indexes = ()
constraints = (
models.UniqueConstraint(
fields=('parent', 'name'),
@@ -318,6 +324,9 @@ class Location(ContactsMixin, ImageAttachmentsMixin, NestedGroupModel):
class Meta:
ordering = ['site', 'name']
# Empty tuple triggers Django migration detection for MPTT indexes
# (see #21016, django-mptt/django-mptt#682)
indexes = ()
constraints = (
models.UniqueConstraint(
fields=('site', 'parent', 'name'),

View File

@@ -143,6 +143,10 @@ class NestedGroupModel(OwnerMixin, NetBoxModel, MPTTModel):
"""
Base model for objects which are used to form a hierarchy (regions, locations, etc.). These models nest
recursively using MPTT. Within each parent, each child instance must have a unique name.
Note: django-mptt injects the (tree_id, lft) index dynamically, but Django's migration autodetector won't
detect it unless concrete subclasses explicitly declare Meta.indexes (even as an empty tuple). See #21016
and django-mptt/django-mptt#682.
"""
parent = TreeForeignKey(
to='self',

View File

@@ -0,0 +1,23 @@
# Generated by Django 5.2.10 on 2026-02-13 13:36
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('extras', '0134_owner'),
('tenancy', '0022_add_comments_to_organizationalmodel'),
('users', '0015_owner'),
]
operations = [
migrations.AddIndex(
model_name='contactgroup',
index=models.Index(fields=['tree_id', 'lft'], name='tenancy_contactgroup_tree_d2ce'),
),
migrations.AddIndex(
model_name='tenantgroup',
index=models.Index(fields=['tree_id', 'lft'], name='tenancy_tenantgroup_tree_ifebc'),
),
]

View File

@@ -22,6 +22,9 @@ class ContactGroup(NestedGroupModel):
"""
class Meta:
ordering = ['name']
# Empty tuple triggers Django migration detection for MPTT indexes
# (see #21016, django-mptt/django-mptt#682)
indexes = ()
constraints = (
models.UniqueConstraint(
fields=('parent', 'name'),

View File

@@ -29,6 +29,9 @@ class TenantGroup(NestedGroupModel):
class Meta:
ordering = ['name']
# Empty tuple triggers Django migration detection for MPTT indexes
# (see #21016, django-mptt/django-mptt#682)
indexes = ()
verbose_name = _('tenant group')
verbose_name_plural = _('tenant groups')

View File

@@ -0,0 +1,19 @@
# Generated by Django 5.2.10 on 2026-02-13 13:36
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('extras', '0134_owner'),
('users', '0015_owner'),
('wireless', '0017_gfk_indexes'),
]
operations = [
migrations.AddIndex(
model_name='wirelesslangroup',
index=models.Index(fields=['tree_id', 'lft'], name='wireless_wirelesslangroup_fbcd'),
),
]

View File

@@ -63,6 +63,9 @@ class WirelessLANGroup(NestedGroupModel):
class Meta:
ordering = ('name', 'pk')
# Empty tuple triggers Django migration detection for MPTT indexes
# (see #21016, django-mptt/django-mptt#682)
indexes = ()
constraints = (
models.UniqueConstraint(
fields=('parent', 'name'),

View File

@@ -5,7 +5,7 @@ django-debug-toolbar==6.2.0
django-filter==25.2
django-graphiql-debug-toolbar==0.2.0
django-htmx==1.27.0
django-mptt==0.17.0
django-mptt==0.18.0
django-pglocks==1.0.4
django-prometheus==2.4.1
django-redis==6.0.0