7699 use mixin for model

This commit is contained in:
Arthur Hanson 2024-10-24 11:19:47 -07:00
parent c73902c088
commit cfdab0e87f
3 changed files with 70 additions and 61 deletions

View File

@ -2,6 +2,7 @@ import json
from collections import defaultdict
from functools import cached_property
from django.apps import apps
from django.contrib.contenttypes.fields import GenericRelation
from django.core.validators import ValidationError
from django.db import models
@ -23,6 +24,7 @@ from utilities.views import register_model_view
__all__ = (
'BookmarksMixin',
'CachedLocationScopeMixin',
'ChangeLoggingMixin',
'CloningMixin',
'ContactsMixin',
@ -580,6 +582,68 @@ class SyncedDataMixin(models.Model):
))
class CachedLocationScopeMixin(models.Model):
"""
Cached associations for scope to enable efficient filtering - must define scope and scope_type on model
"""
_location = models.ForeignKey(
to='dcim.Location',
on_delete=models.CASCADE,
related_name='_%(class)ss',
blank=True,
null=True
)
_site = models.ForeignKey(
to='dcim.Site',
on_delete=models.CASCADE,
related_name='_%(class)ss',
blank=True,
null=True
)
_region = models.ForeignKey(
to='dcim.Region',
on_delete=models.CASCADE,
related_name='_%(class)ss',
blank=True,
null=True
)
_sitegroup = models.ForeignKey(
to='dcim.SiteGroup',
on_delete=models.CASCADE,
related_name='_%(class)ss',
blank=True,
null=True
)
class Meta:
abstract = True
def save(self, *args, **kwargs):
# Cache objects associated with the terminating object (for filtering)
self.cache_related_objects()
super().save(*args, **kwargs)
def cache_related_objects(self):
self._region = self._sitegroup = self._site = self._location = None
if self.scope_type:
scope_type = self.scope_type.model_class()
if scope_type == apps.get_model('dcim', 'region'):
self._region = self.scope
elif scope_type == apps.get_model('dcim', 'sitegroup'):
self._sitegroup = self.scope
elif scope_type == apps.get_model('dcim', 'site'):
self._region = self.scope.region
self._sitegroup = self.scope.group
self._site = self.scope
elif scope_type == apps.get_model('dcim', 'location'):
self._region = self.scope.site.region
self._sitegroup = self.scope.site.group
self._site = self.scope.site
self._location = self.scope
cache_related_objects.alters_data = True
#
# Feature registration
#

View File

@ -32,7 +32,7 @@ class Migration(migrations.Migration):
blank=True,
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name='_clusters',
related_name='_%(class)ss',
to='dcim.location',
),
),
@ -43,7 +43,7 @@ class Migration(migrations.Migration):
blank=True,
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name='_clusters',
related_name='_%(class)ss',
to='dcim.region',
),
),
@ -54,7 +54,7 @@ class Migration(migrations.Migration):
blank=True,
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name='_clusters',
related_name='_%(class)ss',
to='dcim.site',
),
),
@ -65,7 +65,7 @@ class Migration(migrations.Migration):
blank=True,
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name='_clusters',
related_name='_%(class)ss',
to='dcim.sitegroup',
),
),

View File

@ -6,7 +6,7 @@ from django.utils.translation import gettext_lazy as _
from dcim.models import Device
from netbox.models import OrganizationalModel, PrimaryModel
from netbox.models.features import ContactsMixin
from netbox.models.features import CachedLocationScopeMixin, ContactsMixin
from virtualization.choices import *
from virtualization.constants import CLUSTER_SCOPE_TYPES
@ -44,7 +44,7 @@ class ClusterGroup(ContactsMixin, OrganizationalModel):
verbose_name_plural = _('cluster groups')
class Cluster(ContactsMixin, PrimaryModel):
class Cluster(ContactsMixin, CachedLocationScopeMixin, PrimaryModel):
"""
A cluster of VirtualMachines. Each Cluster may optionally be associated with one or more Devices.
"""
@ -103,36 +103,6 @@ class Cluster(ContactsMixin, PrimaryModel):
related_query_name='cluster'
)
# Cached associations to enable efficient filtering
_location = models.ForeignKey(
to='dcim.Location',
on_delete=models.CASCADE,
related_name='_clusters',
blank=True,
null=True
)
_site = models.ForeignKey(
to='dcim.Site',
on_delete=models.CASCADE,
related_name='_clusters',
blank=True,
null=True
)
_region = models.ForeignKey(
to='dcim.Region',
on_delete=models.CASCADE,
related_name='_clusters',
blank=True,
null=True
)
_sitegroup = models.ForeignKey(
to='dcim.SiteGroup',
on_delete=models.CASCADE,
related_name='_clusters',
blank=True,
null=True
)
clone_fields = (
'scope_type', 'scope_id', 'type', 'group', 'status', 'tenant',
)
@ -180,28 +150,3 @@ class Cluster(ContactsMixin, PrimaryModel):
"{count} devices are assigned as hosts for this cluster but are not in site {site}"
).format(count=nonsite_devices, site=site)
})
def save(self, *args, **kwargs):
# Cache objects associated with the terminating object (for filtering)
self.cache_related_objects()
super().save(*args, **kwargs)
def cache_related_objects(self):
self._region = self._sitegroup = self._site = self._location = None
if self.scope_type:
scope_type = self.scope_type.model_class()
if scope_type == apps.get_model('dcim', 'region'):
self._region = self.scope
elif scope_type == apps.get_model('dcim', 'sitegroup'):
self._sitegroup = self.scope
elif scope_type == apps.get_model('dcim', 'site'):
self._region = self.scope.region
self._sitegroup = self.scope.group
self._site = self.scope
elif scope_type == apps.get_model('dcim', 'location'):
self._region = self.scope.site.region
self._sitegroup = self.scope.site.group
self._site = self.scope.site
self._location = self.scope
cache_related_objects.alters_data = True