12552 initial removal of mptt

This commit is contained in:
Arthur 2023-05-18 13:22:31 -07:00
parent 4208b79514
commit da0c459e73
24 changed files with 531 additions and 275 deletions

View File

@ -26,9 +26,9 @@ django-filter
# https://github.com/flavors/django-graphiql-debug-toolbar/blob/main/CHANGES.rst
django-graphiql-debug-toolbar
# Modified Preorder Tree Traversal (recursive nesting of objects)
# https://github.com/django-mptt/django-mptt/blob/main/CHANGELOG.rst
django-mptt
# Adjacency-list trees for Django using recursive common table expressions.
# https://github.com/matthiask/django-tree-queries/blob/main/CHANGELOG.rst
django-tree-queries
# Context managers for PostgreSQL advisory locks
# https://github.com/Xof/django-pglocks/blob/master/CHANGES.txt

View File

@ -60,7 +60,7 @@ __all__ = [
class NestedRegionSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:region-detail')
site_count = serializers.IntegerField(read_only=True)
_depth = serializers.IntegerField(source='level', read_only=True)
_depth = serializers.IntegerField(source='tree_depth', read_only=True)
class Meta:
model = models.Region
@ -73,7 +73,7 @@ class NestedRegionSerializer(WritableNestedSerializer):
class NestedSiteGroupSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:sitegroup-detail')
site_count = serializers.IntegerField(read_only=True)
_depth = serializers.IntegerField(source='level', read_only=True)
_depth = serializers.IntegerField(source='tree_depth', read_only=True)
class Meta:
model = models.SiteGroup
@ -98,7 +98,7 @@ class NestedSiteSerializer(WritableNestedSerializer):
class NestedLocationSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:location-detail')
rack_count = serializers.IntegerField(read_only=True)
_depth = serializers.IntegerField(source='level', read_only=True)
_depth = serializers.IntegerField(source='tree_depth', read_only=True)
class Meta:
model = models.Location
@ -258,7 +258,7 @@ class NestedDeviceBayTemplateSerializer(WritableNestedSerializer):
class NestedInventoryItemTemplateSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:inventoryitemtemplate-detail')
_depth = serializers.IntegerField(source='level', read_only=True)
_depth = serializers.IntegerField(source='tree_depth', read_only=True)
class Meta:
model = models.InventoryItemTemplate
@ -433,7 +433,7 @@ class NestedDeviceBaySerializer(WritableNestedSerializer):
class NestedInventoryItemSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:inventoryitem-detail')
device = NestedDeviceSerializer(read_only=True)
_depth = serializers.IntegerField(source='level', read_only=True)
_depth = serializers.IntegerField(source='tree_depth', read_only=True)
class Meta:
model = models.InventoryItem

View File

@ -589,7 +589,7 @@ class InventoryItemTemplateSerializer(ValidatedModelSerializer):
allow_null=True
)
component = serializers.SerializerMethodField(read_only=True)
_depth = serializers.IntegerField(source='level', read_only=True)
_depth = serializers.IntegerField(source='tree_depth', read_only=True)
class Meta:
model = InventoryItemTemplate
@ -1023,7 +1023,7 @@ class InventoryItemSerializer(NetBoxModelSerializer):
allow_null=True
)
component = serializers.SerializerMethodField(read_only=True)
_depth = serializers.IntegerField(source='level', read_only=True)
_depth = serializers.IntegerField(source='tree_depth', read_only=True)
class Meta:
model = InventoryItem

View File

@ -99,13 +99,14 @@ class PassThroughPortMixin(object):
#
class RegionViewSet(NetBoxModelViewSet):
queryset = Region.objects.add_related_count(
Region.objects.all(),
Site,
'region',
'site_count',
cumulative=True
).prefetch_related('tags')
queryset = Region.objects.all().prefetch_related('tags')
# queryset = Region.objects.add_related_count(
# Region.objects.all(),
# Site,
# 'region',
# 'site_count',
# cumulative=True
# ).prefetch_related('tags')
serializer_class = serializers.RegionSerializer
filterset_class = filtersets.RegionFilterSet
@ -115,13 +116,14 @@ class RegionViewSet(NetBoxModelViewSet):
#
class SiteGroupViewSet(NetBoxModelViewSet):
queryset = SiteGroup.objects.add_related_count(
SiteGroup.objects.all(),
Site,
'group',
'site_count',
cumulative=True
).prefetch_related('tags')
queryset = SiteGroup.objects.all().prefetch_related('tags')
# queryset = SiteGroup.objects.add_related_count(
# SiteGroup.objects.all(),
# Site,
# 'group',
# 'site_count',
# cumulative=True
# ).prefetch_related('tags')
serializer_class = serializers.SiteGroupSerializer
filterset_class = filtersets.SiteGroupFilterSet
@ -150,19 +152,20 @@ class SiteViewSet(NetBoxModelViewSet):
#
class LocationViewSet(NetBoxModelViewSet):
queryset = Location.objects.add_related_count(
Location.objects.add_related_count(
Location.objects.all(),
Device,
'location',
'device_count',
cumulative=True
),
Rack,
'location',
'rack_count',
cumulative=True
).prefetch_related('site', 'tags')
queryset = Location.objects.all().prefetch_related('site', 'tags')
# queryset = Location.objects.add_related_count(
# Location.objects.add_related_count(
# Location.objects.all(),
# Device,
# 'location',
# 'device_count',
# cumulative=True
# ),
# Rack,
# 'location',
# 'rack_count',
# cumulative=True
# ).prefetch_related('site', 'tags')
serializer_class = serializers.LocationSerializer
filterset_class = filtersets.LocationFilterSet

View File

@ -0,0 +1,148 @@
# Generated by Django 4.1.8 on 2023-05-18 20:20
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('dcim', '0173_remove_napalm_fields'),
]
operations = [
migrations.RemoveField(
model_name='inventoryitem',
name='level',
),
migrations.RemoveField(
model_name='inventoryitem',
name='lft',
),
migrations.RemoveField(
model_name='inventoryitem',
name='rght',
),
migrations.RemoveField(
model_name='inventoryitem',
name='tree_id',
),
migrations.RemoveField(
model_name='inventoryitemtemplate',
name='level',
),
migrations.RemoveField(
model_name='inventoryitemtemplate',
name='lft',
),
migrations.RemoveField(
model_name='inventoryitemtemplate',
name='rght',
),
migrations.RemoveField(
model_name='inventoryitemtemplate',
name='tree_id',
),
migrations.RemoveField(
model_name='location',
name='level',
),
migrations.RemoveField(
model_name='location',
name='lft',
),
migrations.RemoveField(
model_name='location',
name='rght',
),
migrations.RemoveField(
model_name='location',
name='tree_id',
),
migrations.RemoveField(
model_name='region',
name='level',
),
migrations.RemoveField(
model_name='region',
name='lft',
),
migrations.RemoveField(
model_name='region',
name='rght',
),
migrations.RemoveField(
model_name='region',
name='tree_id',
),
migrations.RemoveField(
model_name='sitegroup',
name='level',
),
migrations.RemoveField(
model_name='sitegroup',
name='lft',
),
migrations.RemoveField(
model_name='sitegroup',
name='rght',
),
migrations.RemoveField(
model_name='sitegroup',
name='tree_id',
),
migrations.AlterField(
model_name='inventoryitem',
name='parent',
field=models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name='children',
to='dcim.inventoryitem',
),
),
migrations.AlterField(
model_name='inventoryitemtemplate',
name='parent',
field=models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name='children',
to='dcim.inventoryitemtemplate',
),
),
migrations.AlterField(
model_name='location',
name='parent',
field=models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name='children',
to='dcim.location',
),
),
migrations.AlterField(
model_name='region',
name='parent',
field=models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name='children',
to='dcim.region',
),
),
migrations.AlterField(
model_name='sitegroup',
name='parent',
field=models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name='children',
to='dcim.sitegroup',
),
),
]

View File

@ -4,14 +4,14 @@ from django.core.exceptions import ValidationError
from django.core.validators import MaxValueValidator, MinValueValidator
from django.db import models
from django.utils.translation import gettext as _
from mptt.models import MPTTModel, TreeForeignKey
from tree_queries.models import TreeNode
from dcim.choices import *
from dcim.constants import *
from netbox.models import ChangeLoggedModel
from utilities.fields import ColorField, NaturalOrderingField
from utilities.mptt import TreeManager
from utilities.ordering import naturalize_interface
from utilities.tree_queries import TreeManager
from .device_components import (
ConsolePort, ConsoleServerPort, DeviceBay, FrontPort, Interface, InventoryItem, ModuleBay, PowerOutlet, PowerPort,
RearPort,
@ -618,18 +618,10 @@ class DeviceBayTemplate(ComponentTemplateModel):
}
class InventoryItemTemplate(MPTTModel, ComponentTemplateModel):
class InventoryItemTemplate(TreeNode, ComponentTemplateModel):
"""
A template for an InventoryItem to be created for a new parent Device.
"""
parent = TreeForeignKey(
to='self',
on_delete=models.CASCADE,
related_name='child_items',
blank=True,
null=True,
db_index=True
)
component_type = models.ForeignKey(
to=ContentType,
limit_choices_to=MODULAR_COMPONENT_TEMPLATE_MODELS,

View File

@ -8,7 +8,7 @@ from django.db import models
from django.db.models import Sum
from django.urls import reverse
from django.utils.translation import gettext as _
from mptt.models import MPTTModel, TreeForeignKey
from tree_queries.models import TreeNode
from dcim.choices import *
from dcim.constants import *
@ -16,9 +16,9 @@ from dcim.fields import MACAddressField, WWNField
from netbox.models import OrganizationalModel, NetBoxModel
from utilities.choices import ColorChoices
from utilities.fields import ColorField, NaturalOrderingField
from utilities.mptt import TreeManager
from utilities.ordering import naturalize_interface
from utilities.query_functions import CollateAsChar
from utilities.tree_queries import TreeManager
from wireless.choices import *
from wireless.utils import get_channel_attr
@ -1064,19 +1064,11 @@ class InventoryItemRole(OrganizationalModel):
return reverse('dcim:inventoryitemrole', args=[self.pk])
class InventoryItem(MPTTModel, ComponentModel):
class InventoryItem(TreeNode, ComponentModel):
"""
An InventoryItem represents a serialized piece of hardware within a Device, such as a line card or power supply.
InventoryItems are used only for inventory purposes.
"""
parent = TreeForeignKey(
to='self',
on_delete=models.CASCADE,
related_name='child_items',
blank=True,
null=True,
db_index=True
)
component_type = models.ForeignKey(
to=ContentType,
limit_choices_to=MODULAR_COMPONENT_MODELS,

View File

@ -198,13 +198,14 @@ class PathTraceView(generic.ObjectView):
#
class RegionListView(generic.ObjectListView):
queryset = Region.objects.add_related_count(
Region.objects.all(),
Site,
'region',
'site_count',
cumulative=True
)
queryset = Region.objects.all()
# queryset = Region.objects.add_related_count(
# Region.objects.all(),
# Site,
# 'region',
# 'site_count',
# cumulative=True
# )
filterset = filtersets.RegionFilterSet
filterset_form = forms.RegionFilterForm
table = tables.RegionTable
@ -244,26 +245,28 @@ class RegionBulkImportView(generic.BulkImportView):
class RegionBulkEditView(generic.BulkEditView):
queryset = Region.objects.add_related_count(
Region.objects.all(),
Site,
'region',
'site_count',
cumulative=True
)
queryset = Region.objects.all()
# queryset = Region.objects.add_related_count(
# Region.objects.all(),
# Site,
# 'region',
# 'site_count',
# cumulative=True
# )
filterset = filtersets.RegionFilterSet
table = tables.RegionTable
form = forms.RegionBulkEditForm
class RegionBulkDeleteView(generic.BulkDeleteView):
queryset = Region.objects.add_related_count(
Region.objects.all(),
Site,
'region',
'site_count',
cumulative=True
)
queryset = Region.objects.all()
# queryset = Region.objects.add_related_count(
# Region.objects.all(),
# Site,
# 'region',
# 'site_count',
# cumulative=True
# )
filterset = filtersets.RegionFilterSet
table = tables.RegionTable
@ -278,13 +281,14 @@ class RegionContactsView(ObjectContactsView):
#
class SiteGroupListView(generic.ObjectListView):
queryset = SiteGroup.objects.add_related_count(
SiteGroup.objects.all(),
Site,
'group',
'site_count',
cumulative=True
)
queryset = SiteGroup.objects.all()
# queryset = SiteGroup.objects.add_related_count(
# SiteGroup.objects.all(),
# Site,
# 'group',
# 'site_count',
# cumulative=True
# )
filterset = filtersets.SiteGroupFilterSet
filterset_form = forms.SiteGroupFilterForm
table = tables.SiteGroupTable
@ -324,26 +328,28 @@ class SiteGroupBulkImportView(generic.BulkImportView):
class SiteGroupBulkEditView(generic.BulkEditView):
queryset = SiteGroup.objects.add_related_count(
SiteGroup.objects.all(),
Site,
'group',
'site_count',
cumulative=True
)
queryset = SiteGroup.objects.all()
# queryset = SiteGroup.objects.add_related_count(
# SiteGroup.objects.all(),
# Site,
# 'group',
# 'site_count',
# cumulative=True
# )
filterset = filtersets.SiteGroupFilterSet
table = tables.SiteGroupTable
form = forms.SiteGroupBulkEditForm
class SiteGroupBulkDeleteView(generic.BulkDeleteView):
queryset = SiteGroup.objects.add_related_count(
SiteGroup.objects.all(),
Site,
'group',
'site_count',
cumulative=True
)
queryset = SiteGroup.objects.all()
# queryset = SiteGroup.objects.add_related_count(
# SiteGroup.objects.all(),
# Site,
# 'group',
# 'site_count',
# cumulative=True
# )
filterset = filtersets.SiteGroupFilterSet
table = tables.SiteGroupTable
@ -388,20 +394,21 @@ class SiteView(generic.ObjectView):
(Circuit.objects.restrict(request.user, 'view').filter(terminations__site=instance).distinct(), 'site_id'),
)
locations = Location.objects.add_related_count(
Location.objects.all(),
Rack,
'location',
'rack_count',
cumulative=True
)
locations = Location.objects.add_related_count(
locations,
Device,
'location',
'device_count',
cumulative=True
).restrict(request.user, 'view').filter(site=instance)
locations = Location.objects.all().restrict(request.user, 'view').filter(site=instance)
# locations = Location.objects.add_related_count(
# Location.objects.all(),
# Rack,
# 'location',
# 'rack_count',
# cumulative=True
# )
# locations = Location.objects.add_related_count(
# locations,
# Device,
# 'location',
# 'device_count',
# cumulative=True
# ).restrict(request.user, 'view').filter(site=instance)
nonracked_devices = Device.objects.filter(
site=instance,
@ -456,19 +463,20 @@ class SiteContactsView(ObjectContactsView):
#
class LocationListView(generic.ObjectListView):
queryset = Location.objects.add_related_count(
Location.objects.add_related_count(
Location.objects.all(),
Device,
'location',
'device_count',
cumulative=True
),
Rack,
'location',
'rack_count',
cumulative=True
)
queryset = Location.objects.all()
# queryset = Location.objects.add_related_count(
# Location.objects.add_related_count(
# Location.objects.all(),
# Device,
# 'location',
# 'device_count',
# cumulative=True
# ),
# Rack,
# 'location',
# 'rack_count',
# cumulative=True
# )
filterset = filtersets.LocationFilterSet
filterset_form = forms.LocationFilterForm
table = tables.LocationTable
@ -515,26 +523,28 @@ class LocationBulkImportView(generic.BulkImportView):
class LocationBulkEditView(generic.BulkEditView):
queryset = Location.objects.add_related_count(
Location.objects.all(),
Rack,
'location',
'rack_count',
cumulative=True
).prefetch_related('site')
queryset = Location.objects.all()
# queryset = Location.objects.add_related_count(
# Location.objects.all(),
# Rack,
# 'location',
# 'rack_count',
# cumulative=True
# ).prefetch_related('site')
filterset = filtersets.LocationFilterSet
table = tables.LocationTable
form = forms.LocationBulkEditForm
class LocationBulkDeleteView(generic.BulkDeleteView):
queryset = Location.objects.add_related_count(
Location.objects.all(),
Rack,
'location',
'rack_count',
cumulative=True
).prefetch_related('site')
queryset = Location.objects.all()
# queryset = Location.objects.add_related_count(
# Location.objects.all(),
# Rack,
# 'location',
# 'rack_count',
# cumulative=True
# ).prefetch_related('site')
filterset = filtersets.LocationFilterSet
table = tables.LocationTable

View File

@ -130,10 +130,11 @@ class ConfigContextModelQuerySet(RestrictedQuerySet):
region_field = 'cluster__site__region'
sitegroup_field = 'cluster__site__group'
"""
base_query.add(
(Q(
regions__tree_id=OuterRef(f'{region_field}__tree_id'),
regions__level__lte=OuterRef(f'{region_field}__level'),
regions__tree_depth__lte=OuterRef(f'{region_field}__tree_depth'),
regions__lft__lte=OuterRef(f'{region_field}__lft'),
regions__rght__gte=OuterRef(f'{region_field}__rght'),
) | Q(regions=None)),
@ -143,11 +144,12 @@ class ConfigContextModelQuerySet(RestrictedQuerySet):
base_query.add(
(Q(
site_groups__tree_id=OuterRef(f'{sitegroup_field}__tree_id'),
site_groups__level__lte=OuterRef(f'{sitegroup_field}__level'),
site_groups__tree_depth__lte=OuterRef(f'{sitegroup_field}__tree_depth'),
site_groups__lft__lte=OuterRef(f'{sitegroup_field}__lft'),
site_groups__rght__gte=OuterRef(f'{sitegroup_field}__rght'),
) | Q(site_groups=None)),
Q.AND
)
"""
return base_query

View File

@ -21,7 +21,7 @@ class NestedGroupModelSerializer(NetBoxModelSerializer):
"""
Extends PrimaryModelSerializer to include MPTT support.
"""
_depth = serializers.IntegerField(source='level', read_only=True)
_depth = serializers.IntegerField(source='tree_depth', read_only=True)
class BulkOperationSerializer(serializers.Serializer):

View File

@ -2,11 +2,11 @@ from django.conf import settings
from django.contrib.contenttypes.fields import GenericForeignKey
from django.core.validators import ValidationError
from django.db import models
from mptt.models import MPTTModel, TreeForeignKey
from tree_queries.models import TreeNode
from netbox.models.features import *
from utilities.mptt import TreeManager
from utilities.querysets import RestrictedQuerySet
from utilities.tree_queries import TreeManager
__all__ = (
'ChangeLoggedModel',
@ -103,19 +103,11 @@ class PrimaryModel(NetBoxModel):
abstract = True
class NestedGroupModel(CloningMixin, NetBoxFeatureSet, MPTTModel):
class NestedGroupModel(CloningMixin, NetBoxFeatureSet, TreeNode):
"""
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.
"""
parent = TreeForeignKey(
to='self',
on_delete=models.CASCADE,
related_name='children',
blank=True,
null=True,
db_index=True
)
name = models.CharField(
max_length=100
)
@ -131,9 +123,7 @@ class NestedGroupModel(CloningMixin, NetBoxFeatureSet, MPTTModel):
class Meta:
abstract = True
class MPTTMeta:
order_insertion_by = ('name',)
ordering = ("name",)
def __str__(self):
return self.name

View File

@ -24,7 +24,7 @@ __all__ = [
class NestedTenantGroupSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(view_name='tenancy-api:tenantgroup-detail')
tenant_count = serializers.IntegerField(read_only=True)
_depth = serializers.IntegerField(source='level', read_only=True)
_depth = serializers.IntegerField(source='tree_depth', read_only=True)
class Meta:
model = TenantGroup
@ -49,7 +49,7 @@ class NestedTenantSerializer(WritableNestedSerializer):
class NestedContactGroupSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(view_name='tenancy-api:contactgroup-detail')
contact_count = serializers.IntegerField(read_only=True)
_depth = serializers.IntegerField(source='level', read_only=True)
_depth = serializers.IntegerField(source='tree_depth', read_only=True)
class Meta:
model = ContactGroup

View File

@ -24,13 +24,14 @@ class TenancyRootView(APIRootView):
#
class TenantGroupViewSet(NetBoxModelViewSet):
queryset = TenantGroup.objects.add_related_count(
TenantGroup.objects.all(),
Tenant,
'group',
'tenant_count',
cumulative=True
).prefetch_related('tags')
queryset = TenantGroup.objects.all().prefetch_related('tags')
# queryset = TenantGroup.objects.add_related_count(
# TenantGroup.objects.all(),
# Tenant,
# 'group',
# 'tenant_count',
# cumulative=True
# ).prefetch_related('tags')
serializer_class = serializers.TenantGroupSerializer
filterset_class = filtersets.TenantGroupFilterSet
@ -59,13 +60,14 @@ class TenantViewSet(NetBoxModelViewSet):
#
class ContactGroupViewSet(NetBoxModelViewSet):
queryset = ContactGroup.objects.add_related_count(
ContactGroup.objects.all(),
Contact,
'group',
'contact_count',
cumulative=True
).prefetch_related('tags')
queryset = ContactGroup.objects.all().prefetch_related('tags')
# queryset = ContactGroup.objects.add_related_count(
# ContactGroup.objects.all(),
# Contact,
# 'group',
# 'contact_count',
# cumulative=True
# ).prefetch_related('tags')
serializer_class = serializers.ContactGroupSerializer
filterset_class = filtersets.ContactGroupFilterSet

View File

@ -0,0 +1,67 @@
# Generated by Django 4.1.8 on 2023-05-18 20:20
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('tenancy', '0010_tenant_relax_uniqueness'),
]
operations = [
migrations.RemoveField(
model_name='contactgroup',
name='level',
),
migrations.RemoveField(
model_name='contactgroup',
name='lft',
),
migrations.RemoveField(
model_name='contactgroup',
name='rght',
),
migrations.RemoveField(
model_name='contactgroup',
name='tree_id',
),
migrations.RemoveField(
model_name='tenantgroup',
name='level',
),
migrations.RemoveField(
model_name='tenantgroup',
name='lft',
),
migrations.RemoveField(
model_name='tenantgroup',
name='rght',
),
migrations.RemoveField(
model_name='tenantgroup',
name='tree_id',
),
migrations.AlterField(
model_name='contactgroup',
name='parent',
field=models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name='children',
to='tenancy.contactgroup',
),
),
migrations.AlterField(
model_name='tenantgroup',
name='parent',
field=models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name='children',
to='tenancy.tenantgroup',
),
),
]

View File

@ -42,13 +42,14 @@ class ObjectContactsView(generic.ObjectChildrenView):
class TenantGroupListView(generic.ObjectListView):
queryset = TenantGroup.objects.add_related_count(
TenantGroup.objects.all(),
Tenant,
'group',
'tenant_count',
cumulative=True
)
queryset = TenantGroup.objects.all()
# queryset = TenantGroup.objects.add_related_count(
# TenantGroup.objects.all(),
# Tenant,
# 'group',
# 'tenant_count',
# cumulative=True
# )
filterset = filtersets.TenantGroupFilterSet
filterset_form = forms.TenantGroupFilterForm
table = tables.TenantGroupTable
@ -86,26 +87,28 @@ class TenantGroupBulkImportView(generic.BulkImportView):
class TenantGroupBulkEditView(generic.BulkEditView):
queryset = TenantGroup.objects.add_related_count(
TenantGroup.objects.all(),
Tenant,
'group',
'tenant_count',
cumulative=True
)
queryset = TenantGroup.objects.all()
# queryset = TenantGroup.objects.add_related_count(
# TenantGroup.objects.all(),
# Tenant,
# 'group',
# 'tenant_count',
# cumulative=True
# )
filterset = filtersets.TenantGroupFilterSet
table = tables.TenantGroupTable
form = forms.TenantGroupBulkEditForm
class TenantGroupBulkDeleteView(generic.BulkDeleteView):
queryset = TenantGroup.objects.add_related_count(
TenantGroup.objects.all(),
Tenant,
'group',
'tenant_count',
cumulative=True
)
queryset = TenantGroup.objects.all()
# queryset = TenantGroup.objects.add_related_count(
# TenantGroup.objects.all(),
# Tenant,
# 'group',
# 'tenant_count',
# cumulative=True
# )
filterset = filtersets.TenantGroupFilterSet
table = tables.TenantGroupTable
@ -198,13 +201,14 @@ class TenantContactsView(ObjectContactsView):
#
class ContactGroupListView(generic.ObjectListView):
queryset = ContactGroup.objects.add_related_count(
ContactGroup.objects.all(),
Contact,
'group',
'contact_count',
cumulative=True
)
queryset = ContactGroup.objects.all()
# queryset = ContactGroup.objects.add_related_count(
# ContactGroup.objects.all(),
# Contact,
# 'group',
# 'contact_count',
# cumulative=True
# )
filterset = filtersets.ContactGroupFilterSet
filterset_form = forms.ContactGroupFilterForm
table = tables.ContactGroupTable
@ -242,26 +246,28 @@ class ContactGroupBulkImportView(generic.BulkImportView):
class ContactGroupBulkEditView(generic.BulkEditView):
queryset = ContactGroup.objects.add_related_count(
ContactGroup.objects.all(),
Contact,
'group',
'contact_count',
cumulative=True
)
queryset = ContactGroup.objects.all()
# queryset = ContactGroup.objects.add_related_count(
# ContactGroup.objects.all(),
# Contact,
# 'group',
# 'contact_count',
# cumulative=True
# )
filterset = filtersets.ContactGroupFilterSet
table = tables.ContactGroupTable
form = forms.ContactGroupBulkEditForm
class ContactGroupBulkDeleteView(generic.BulkDeleteView):
queryset = ContactGroup.objects.add_related_count(
ContactGroup.objects.all(),
Contact,
'group',
'contact_count',
cumulative=True
)
queryset = ContactGroup.objects.all()
# queryset = ContactGroup.objects.add_related_count(
# ContactGroup.objects.all(),
# Contact,
# 'group',
# 'contact_count',
# cumulative=True
# )
filterset = filtersets.ContactGroupFilterSet
table = tables.ContactGroupTable

View File

@ -1,24 +0,0 @@
from mptt.managers import TreeManager as TreeManager_
from mptt.querysets import TreeQuerySet as TreeQuerySet_
from django.db.models import Manager
from .querysets import RestrictedQuerySet
__all__ = (
'TreeManager',
'TreeQuerySet',
)
class TreeQuerySet(TreeQuerySet_, RestrictedQuerySet):
"""
Mate django-mptt's TreeQuerySet with our RestrictedQuerySet for permissions enforcement.
"""
pass
class TreeManager(Manager.from_queryset(TreeQuerySet), TreeManager_):
"""
Extend django-mptt's TreeManager to incorporate RestrictedQuerySet().
"""
pass

View File

@ -0,0 +1,25 @@
from tree_queries.query import TreeManager as TreeManager_
from tree_queries.query import TreeQuerySet as TreeQuerySet_
from django.db.models import Manager
from .querysets import RestrictedQuerySet
__all__ = (
'TreeManager',
'TreeQuerySet',
)
class TreeQuerySet(TreeQuerySet_, RestrictedQuerySet):
"""
Mate django-tree-queries TreeQuerySet with our RestrictedQuerySet for permissions enforcement.
"""
pass
class TreeManager(Manager.from_queryset(TreeQuerySet), TreeManager_):
"""
Extend django-tree-queries TreeManager to incorporate RestrictedQuerySet().
"""
_with_tree_fields = True

View File

@ -15,7 +15,7 @@ from django.utils.html import escape
from django.utils import timezone
from django.utils.timezone import localtime
from jinja2.sandbox import SandboxedEnvironment
from mptt.models import MPTTModel
from tree_queries.models import TreeNode
from dcim.choices import CableLengthUnitChoices, WeightUnitChoices
from extras.plugins import PluginConfig
@ -153,8 +153,8 @@ def serialize_object(obj, resolve_tags=True, extra=None):
json_str = serializers.serialize('json', [obj])
data = json.loads(json_str)[0]['fields']
# Exclude any MPTTModel fields
if issubclass(obj.__class__, MPTTModel):
# Exclude any TreeNode fields
if issubclass(obj.__class__, TreeNode):
for field in ['level', 'lft', 'rght', 'tree_id']:
data.pop(field)

View File

@ -17,7 +17,7 @@ __all__ = (
class NestedWirelessLANGroupSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(view_name='wireless-api:wirelesslangroup-detail')
wirelesslan_count = serializers.IntegerField(read_only=True)
_depth = serializers.IntegerField(source='level', read_only=True)
_depth = serializers.IntegerField(source='tree_depth', read_only=True)
class Meta:
model = WirelessLANGroup

View File

@ -15,13 +15,14 @@ class WirelessRootView(APIRootView):
class WirelessLANGroupViewSet(NetBoxModelViewSet):
queryset = WirelessLANGroup.objects.add_related_count(
WirelessLANGroup.objects.all(),
WirelessLAN,
'group',
'wirelesslan_count',
cumulative=True
)
queryset = WirelessLANGroup.objects.all()
# queryset = WirelessLANGroup.objects.add_related_count(
# WirelessLANGroup.objects.all(),
# WirelessLAN,
# 'group',
# 'wirelesslan_count',
# cumulative=True
# )
serializer_class = serializers.WirelessLANGroupSerializer
filterset_class = filtersets.WirelessLANGroupFilterSet

View File

@ -0,0 +1,40 @@
# Generated by Django 4.1.8 on 2023-05-18 20:20
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('wireless', '0008_wirelesslan_status'),
]
operations = [
migrations.RemoveField(
model_name='wirelesslangroup',
name='level',
),
migrations.RemoveField(
model_name='wirelesslangroup',
name='lft',
),
migrations.RemoveField(
model_name='wirelesslangroup',
name='rght',
),
migrations.RemoveField(
model_name='wirelesslangroup',
name='tree_id',
),
migrations.AlterField(
model_name='wirelesslangroup',
name='parent',
field=models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name='children',
to='wireless.wirelesslangroup',
),
),
]

View File

@ -1,7 +1,6 @@
from django.core.exceptions import ValidationError
from django.db import models
from django.urls import reverse
from mptt.models import MPTTModel
from dcim.choices import LinkStatusChoices
from dcim.constants import WIRELESS_IFACE_TYPES

View File

@ -11,13 +11,14 @@ from .models import *
#
class WirelessLANGroupListView(generic.ObjectListView):
queryset = WirelessLANGroup.objects.add_related_count(
WirelessLANGroup.objects.all(),
WirelessLAN,
'group',
'wirelesslan_count',
cumulative=True
).prefetch_related('tags')
queryset = WirelessLANGroup.objects.all().prefetch_related('tags')
# queryset = WirelessLANGroup.objects.add_related_count(
# WirelessLANGroup.objects.all(),
# WirelessLAN,
# 'group',
# 'wirelesslan_count',
# cumulative=True
# ).prefetch_related('tags')
filterset = filtersets.WirelessLANGroupFilterSet
filterset_form = forms.WirelessLANGroupFilterForm
table = tables.WirelessLANGroupTable
@ -55,26 +56,28 @@ class WirelessLANGroupBulkImportView(generic.BulkImportView):
class WirelessLANGroupBulkEditView(generic.BulkEditView):
queryset = WirelessLANGroup.objects.add_related_count(
WirelessLANGroup.objects.all(),
WirelessLAN,
'group',
'wirelesslan_count',
cumulative=True
)
queryset = WirelessLANGroup.objects.all()
# queryset = WirelessLANGroup.objects.add_related_count(
# WirelessLANGroup.objects.all(),
# WirelessLAN,
# 'group',
# 'wirelesslan_count',
# cumulative=True
# )
filterset = filtersets.WirelessLANGroupFilterSet
table = tables.WirelessLANGroupTable
form = forms.WirelessLANGroupBulkEditForm
class WirelessLANGroupBulkDeleteView(generic.BulkDeleteView):
queryset = WirelessLANGroup.objects.add_related_count(
WirelessLANGroup.objects.all(),
WirelessLAN,
'group',
'wirelesslan_count',
cumulative=True
)
queryset = WirelessLANGroup.objects.all()
# queryset = WirelessLANGroup.objects.add_related_count(
# WirelessLANGroup.objects.all(),
# WirelessLAN,
# 'group',
# 'wirelesslan_count',
# cumulative=True
# )
filterset = filtersets.WirelessLANGroupFilterSet
table = tables.WirelessLANGroupTable

View File

@ -5,7 +5,6 @@ django-cors-headers==3.14.0
django-debug-toolbar==4.0.0
django-filter==23.2
django-graphiql-debug-toolbar==0.2.0
django-mptt==0.14
django-pglocks==1.0.4
django-prometheus==2.3.1
django-redis==5.2.0
@ -14,6 +13,7 @@ django-rq==2.8.0
django-tables2==2.5.3
django-taggit==4.0.0
django-timezone-field==5.0
django-tree-queries==0.14.0
djangorestframework==3.14.0
drf-spectacular==0.26.2
drf-spectacular-sidecar==2023.5.1