|
|
@@ -1,5 +1,4 @@
|
|
|
import netaddr
|
|
|
-from django.apps import apps
|
|
|
from django.contrib.contenttypes.fields import GenericForeignKey
|
|
|
from django.core.exceptions import ValidationError
|
|
|
from django.db import models
|
|
|
@@ -9,6 +8,7 @@ from django.utils.functional import cached_property
|
|
|
from django.utils.translation import gettext_lazy as _
|
|
|
|
|
|
from core.models import ObjectType
|
|
|
+from dcim.models.mixins import CachedScopeMixin
|
|
|
from ipam.choices import *
|
|
|
from ipam.constants import *
|
|
|
from ipam.fields import IPNetworkField, IPAddressField
|
|
|
@@ -198,7 +198,7 @@ class Role(OrganizationalModel):
|
|
|
return self.name
|
|
|
|
|
|
|
|
|
-class Prefix(ContactsMixin, GetAvailablePrefixesMixin, PrimaryModel):
|
|
|
+class Prefix(ContactsMixin, GetAvailablePrefixesMixin, CachedScopeMixin, PrimaryModel):
|
|
|
"""
|
|
|
A Prefix represents an IPv4 or IPv6 network, including mask length. Prefixes can optionally be scoped to certain
|
|
|
areas and/or assigned to VRFs. A Prefix must be assigned a status and may optionally be assigned a used-define Role.
|
|
|
@@ -208,22 +208,6 @@ class Prefix(ContactsMixin, GetAvailablePrefixesMixin, PrimaryModel):
|
|
|
verbose_name=_('prefix'),
|
|
|
help_text=_('IPv4 or IPv6 network with mask')
|
|
|
)
|
|
|
- scope_type = models.ForeignKey(
|
|
|
- to='contenttypes.ContentType',
|
|
|
- on_delete=models.PROTECT,
|
|
|
- limit_choices_to=Q(model__in=PREFIX_SCOPE_TYPES),
|
|
|
- related_name='+',
|
|
|
- blank=True,
|
|
|
- null=True
|
|
|
- )
|
|
|
- scope_id = models.PositiveBigIntegerField(
|
|
|
- blank=True,
|
|
|
- null=True
|
|
|
- )
|
|
|
- scope = GenericForeignKey(
|
|
|
- ct_field='scope_type',
|
|
|
- fk_field='scope_id'
|
|
|
- )
|
|
|
vrf = models.ForeignKey(
|
|
|
to='ipam.VRF',
|
|
|
on_delete=models.PROTECT,
|
|
|
@@ -272,36 +256,6 @@ class Prefix(ContactsMixin, GetAvailablePrefixesMixin, PrimaryModel):
|
|
|
help_text=_("Treat as fully utilized")
|
|
|
)
|
|
|
|
|
|
- # Cached associations to enable efficient filtering
|
|
|
- _location = models.ForeignKey(
|
|
|
- to='dcim.Location',
|
|
|
- on_delete=models.CASCADE,
|
|
|
- related_name='_prefixes',
|
|
|
- blank=True,
|
|
|
- null=True
|
|
|
- )
|
|
|
- _site = models.ForeignKey(
|
|
|
- to='dcim.Site',
|
|
|
- on_delete=models.CASCADE,
|
|
|
- related_name='_prefixes',
|
|
|
- blank=True,
|
|
|
- null=True
|
|
|
- )
|
|
|
- _region = models.ForeignKey(
|
|
|
- to='dcim.Region',
|
|
|
- on_delete=models.CASCADE,
|
|
|
- related_name='_prefixes',
|
|
|
- blank=True,
|
|
|
- null=True
|
|
|
- )
|
|
|
- _sitegroup = models.ForeignKey(
|
|
|
- to='dcim.SiteGroup',
|
|
|
- on_delete=models.CASCADE,
|
|
|
- related_name='_prefixes',
|
|
|
- blank=True,
|
|
|
- null=True
|
|
|
- )
|
|
|
-
|
|
|
# Cached depth & child counts
|
|
|
_depth = models.PositiveSmallIntegerField(
|
|
|
default=0,
|
|
|
@@ -368,25 +322,6 @@ class Prefix(ContactsMixin, GetAvailablePrefixesMixin, PrimaryModel):
|
|
|
|
|
|
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
|
|
|
-
|
|
|
@property
|
|
|
def family(self):
|
|
|
return self.prefix.version if self.prefix else None
|