diff --git a/netbox/dcim/models/mixins.py b/netbox/dcim/models/mixins.py index c9be451a0..ba9050e10 100644 --- a/netbox/dcim/models/mixins.py +++ b/netbox/dcim/models/mixins.py @@ -1,6 +1,8 @@ +from django.apps import apps from django.db import models __all__ = ( + 'CachedScopeMixin', 'RenderConfigMixin', ) @@ -27,3 +29,65 @@ class RenderConfigMixin(models.Model): return self.role.config_template if self.platform and self.platform.config_template: return self.platform.config_template + + +class CachedScopeMixin(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 diff --git a/netbox/netbox/models/features.py b/netbox/netbox/models/features.py index e943afb40..a97227770 100644 --- a/netbox/netbox/models/features.py +++ b/netbox/netbox/models/features.py @@ -2,7 +2,6 @@ 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 @@ -25,7 +24,6 @@ from utilities.views import register_model_view __all__ = ( 'BookmarksMixin', 'ChangeLoggingMixin', - 'CachedScopeMixin', 'CloningMixin', 'ContactsMixin', 'CustomFieldsMixin', @@ -582,68 +580,6 @@ class SyncedDataMixin(models.Model): )) -class CachedScopeMixin(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 # diff --git a/netbox/virtualization/models/clusters.py b/netbox/virtualization/models/clusters.py index 03aef1215..f1ab2b3da 100644 --- a/netbox/virtualization/models/clusters.py +++ b/netbox/virtualization/models/clusters.py @@ -5,8 +5,9 @@ from django.db import models from django.utils.translation import gettext_lazy as _ from dcim.models import Device +from dcim.models.mixins import CachedScopeMixin from netbox.models import OrganizationalModel, PrimaryModel -from netbox.models.features import CachedScopeMixin, ContactsMixin +from netbox.models.features import ContactsMixin from virtualization.choices import * from virtualization.constants import CLUSTER_SCOPE_TYPES