mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-17 04:32:51 -06:00
121 lines
3.7 KiB
Python
121 lines
3.7 KiB
Python
from django.apps import apps
|
|
from django.contrib.contenttypes.fields import GenericForeignKey
|
|
from django.core.exceptions import ValidationError
|
|
from django.db import models
|
|
from django.utils.translation import gettext_lazy as _
|
|
|
|
__all__ = (
|
|
'CachedScopeMixin',
|
|
'RenderConfigMixin',
|
|
)
|
|
|
|
|
|
class RenderConfigMixin(models.Model):
|
|
config_template = models.ForeignKey(
|
|
to='extras.ConfigTemplate',
|
|
on_delete=models.PROTECT,
|
|
related_name='%(class)ss',
|
|
blank=True,
|
|
null=True
|
|
)
|
|
|
|
class Meta:
|
|
abstract = True
|
|
|
|
def get_config_template(self):
|
|
"""
|
|
Return the appropriate ConfigTemplate (if any) for this Device.
|
|
"""
|
|
if self.config_template:
|
|
return self.config_template
|
|
if self.role and self.role.config_template:
|
|
return self.role.config_template
|
|
if self.platform and self.platform.config_template:
|
|
return self.platform.config_template
|
|
|
|
|
|
class CachedScopeMixin(models.Model):
|
|
"""
|
|
Mixin for adding a GenericForeignKey scope to a model that can point to a Region, SiteGroup, Site, or Location.
|
|
Includes cached fields for each to allow efficient filtering. Appropriate validation must be done in the clean()
|
|
method as this does not have any as validation is generally model-specific.
|
|
"""
|
|
scope_type = models.ForeignKey(
|
|
to='contenttypes.ContentType',
|
|
on_delete=models.PROTECT,
|
|
related_name='+',
|
|
blank=True,
|
|
null=True
|
|
)
|
|
scope_id = models.PositiveBigIntegerField(
|
|
blank=True,
|
|
null=True
|
|
)
|
|
scope = GenericForeignKey(
|
|
ct_field='scope_type',
|
|
fk_field='scope_id'
|
|
)
|
|
|
|
_location = models.ForeignKey(
|
|
to='dcim.Location',
|
|
on_delete=models.CASCADE,
|
|
blank=True,
|
|
null=True
|
|
)
|
|
_site = models.ForeignKey(
|
|
to='dcim.Site',
|
|
on_delete=models.CASCADE,
|
|
blank=True,
|
|
null=True
|
|
)
|
|
_region = models.ForeignKey(
|
|
to='dcim.Region',
|
|
on_delete=models.CASCADE,
|
|
blank=True,
|
|
null=True
|
|
)
|
|
_site_group = models.ForeignKey(
|
|
to='dcim.SiteGroup',
|
|
on_delete=models.CASCADE,
|
|
blank=True,
|
|
null=True
|
|
)
|
|
|
|
class Meta:
|
|
abstract = True
|
|
|
|
def clean(self):
|
|
if self.scope_type and not self.scope:
|
|
scope_type = self.scope_type.model_class()
|
|
raise ValidationError({
|
|
'scope': _(
|
|
"Please select a {scope_type}."
|
|
).format(scope_type=scope_type._meta.model_name)
|
|
})
|
|
super().clean()
|
|
|
|
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._site_group = 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._site_group = self.scope
|
|
elif scope_type == apps.get_model('dcim', 'site'):
|
|
self._region = self.scope.region
|
|
self._site_group = self.scope.group
|
|
self._site = self.scope
|
|
elif scope_type == apps.get_model('dcim', 'location'):
|
|
self._region = self.scope.site.region
|
|
self._site_group = self.scope.site.group
|
|
self._site = self.scope.site
|
|
self._location = self.scope
|
|
cache_related_objects.alters_data = True
|