1
0
mirror of https://github.com/netbox-community/netbox.git synced 2024-05-10 07:54:54 +00:00

Use strings to specify prerequisite models

This commit is contained in:
jeremystretch
2022-11-16 17:22:09 -05:00
parent f411c4f439
commit ebf555e1fb
12 changed files with 61 additions and 86 deletions

View File

@ -104,6 +104,10 @@ class Circuit(PrimaryModel):
clone_fields = (
'provider', 'type', 'status', 'tenant', 'install_date', 'termination_date', 'commit_rate', 'description',
)
prerequisite_models = (
'circuits.CircuitType',
'circuits.Provider',
)
class Meta:
ordering = ['provider', 'cid']
@ -117,10 +121,6 @@ class Circuit(PrimaryModel):
def __str__(self):
return self.cid
@classmethod
def get_prerequisite_models(cls):
return [apps.get_model('circuits.Provider'), CircuitType]
def get_absolute_url(self):
return reverse('circuits:circuit', args=[self.pk])

View File

@ -124,6 +124,9 @@ class DeviceType(PrimaryModel, WeightMixin):
clone_fields = (
'manufacturer', 'u_height', 'is_full_depth', 'subdevice_role', 'airflow', 'weight', 'weight_unit'
)
prerequisite_models = (
'dcim.Manufacturer',
)
class Meta:
ordering = ['manufacturer', 'model']
@ -151,10 +154,6 @@ class DeviceType(PrimaryModel, WeightMixin):
self._original_front_image = self.front_image
self._original_rear_image = self.rear_image
@classmethod
def get_prerequisite_models(cls):
return [Manufacturer, ]
def get_absolute_url(self):
return reverse('dcim:devicetype', args=[self.pk])
@ -325,6 +324,9 @@ class ModuleType(PrimaryModel, WeightMixin):
)
clone_fields = ('manufacturer', 'weight', 'weight_unit',)
prerequisite_models = (
'dcim.Manufacturer',
)
class Meta:
ordering = ('manufacturer', 'model')
@ -338,10 +340,6 @@ class ModuleType(PrimaryModel, WeightMixin):
def __str__(self):
return self.model
@classmethod
def get_prerequisite_models(cls):
return [Manufacturer, ]
def get_absolute_url(self):
return reverse('dcim:moduletype', args=[self.pk])
@ -599,6 +597,11 @@ class Device(PrimaryModel, ConfigContextModel):
'device_type', 'device_role', 'tenant', 'platform', 'site', 'location', 'rack', 'face', 'status', 'airflow',
'cluster', 'virtual_chassis',
)
prerequisite_models = (
'dcim.Site',
'dcim.DeviceRole',
'dcim.DeviceType',
)
class Meta:
ordering = ('_name', 'pk') # Name may be null
@ -638,10 +641,6 @@ class Device(PrimaryModel, ConfigContextModel):
return f'{self.device_type.manufacturer} {self.device_type.model} ({self.pk})'
return super().__str__()
@classmethod
def get_prerequisite_models(cls):
return [apps.get_model('dcim.Site'), DeviceRole, DeviceType, ]
def get_absolute_url(self):
return reverse('dcim:device', args=[self.pk])

View File

@ -1,4 +1,3 @@
from django.apps import apps
from django.contrib.contenttypes.fields import GenericRelation
from django.core.exceptions import ValidationError
from django.core.validators import MaxValueValidator, MinValueValidator
@ -48,6 +47,10 @@ class PowerPanel(PrimaryModel):
to='extras.ImageAttachment'
)
prerequisite_models = (
'dcim.Site',
)
class Meta:
ordering = ['site', 'name']
constraints = (
@ -60,10 +63,6 @@ class PowerPanel(PrimaryModel):
def __str__(self):
return self.name
@classmethod
def get_prerequisite_models(cls):
return [apps.get_model('dcim.Site'), ]
def get_absolute_url(self):
return reverse('dcim:powerpanel', args=[self.pk])
@ -137,6 +136,9 @@ class PowerFeed(PrimaryModel, PathEndpoint, CabledObjectModel):
'power_panel', 'rack', 'status', 'type', 'mark_connected', 'supply', 'phase', 'voltage', 'amperage',
'max_utilization',
)
prerequisite_models = (
'dcim.PowerPanel',
)
class Meta:
ordering = ['power_panel', 'name']
@ -150,10 +152,6 @@ class PowerFeed(PrimaryModel, PathEndpoint, CabledObjectModel):
def __str__(self):
return self.name
@classmethod
def get_prerequisite_models(cls):
return [PowerPanel, ]
def get_absolute_url(self):
return reverse('dcim:powerfeed', args=[self.pk])

View File

@ -1,7 +1,6 @@
import decimal
from functools import cached_property
from django.apps import apps
from django.contrib.auth.models import User
from django.contrib.contenttypes.fields import GenericRelation
from django.contrib.postgres.fields import ArrayField
@ -177,6 +176,9 @@ class Rack(PrimaryModel, WeightMixin):
'site', 'location', 'tenant', 'status', 'role', 'type', 'width', 'u_height', 'desc_units', 'outer_width',
'outer_depth', 'outer_unit', 'mounting_depth', 'weight', 'weight_unit',
)
prerequisite_models = (
'dcim.Site',
)
class Meta:
ordering = ('site', 'location', '_name', 'pk') # (site, location, name) may be non-unique
@ -197,10 +199,6 @@ class Rack(PrimaryModel, WeightMixin):
return f'{self.name} ({self.facility_id})'
return self.name
@classmethod
def get_prerequisite_models(cls):
return [apps.get_model('dcim.Site'), ]
def get_absolute_url(self):
return reverse('dcim:rack', args=[self.pk])
@ -488,16 +486,16 @@ class RackReservation(PrimaryModel):
max_length=200
)
prerequisite_models = (
'dcim.Rack',
)
class Meta:
ordering = ['created', 'pk']
def __str__(self):
return "Reservation for rack {}".format(self.rack)
@classmethod
def get_prerequisite_models(cls):
return [apps.get_model('dcim.Site'), Rack, ]
def get_absolute_url(self):
return reverse('dcim:rackreservation', args=[self.pk])

View File

@ -286,6 +286,9 @@ class Location(NestedGroupModel):
)
clone_fields = ('site', 'parent', 'status', 'tenant', 'description')
prerequisite_models = (
'dcim.Site',
)
class Meta:
ordering = ['site', 'name']
@ -312,10 +315,6 @@ class Location(NestedGroupModel):
),
)
@classmethod
def get_prerequisite_models(cls):
return [Site, ]
def get_absolute_url(self):
return reverse('dcim:location', args=[self.pk])

View File

@ -10,7 +10,6 @@ from django.utils.translation import gettext as _
from dcim.fields import ASNField
from dcim.models import Device
from netbox.models import OrganizationalModel, PrimaryModel
from ipam.choices import *
from ipam.constants import *
from ipam.fields import IPNetworkField, IPAddressField
@ -18,9 +17,9 @@ from ipam.managers import IPAddressManager
from ipam.querysets import PrefixQuerySet
from ipam.validators import DNSValidator
from netbox.config import get_config
from netbox.models import OrganizationalModel, PrimaryModel
from virtualization.models import VirtualMachine
__all__ = (
'Aggregate',
'ASN',
@ -101,6 +100,10 @@ class ASN(PrimaryModel):
null=True
)
prerequisite_models = (
'ipam.RIR',
)
class Meta:
ordering = ['asn']
verbose_name = 'ASN'
@ -109,10 +112,6 @@ class ASN(PrimaryModel):
def __str__(self):
return f'AS{self.asn_with_asdot}'
@classmethod
def get_prerequisite_models(cls):
return [RIR, ]
def get_absolute_url(self):
return reverse('ipam:asn', args=[self.pk])
@ -163,6 +162,9 @@ class Aggregate(GetAvailablePrefixesMixin, PrimaryModel):
clone_fields = (
'rir', 'tenant', 'date_added', 'description',
)
prerequisite_models = (
'ipam.RIR',
)
class Meta:
ordering = ('prefix', 'pk') # prefix may be non-unique
@ -170,10 +172,6 @@ class Aggregate(GetAvailablePrefixesMixin, PrimaryModel):
def __str__(self):
return str(self.prefix)
@classmethod
def get_prerequisite_models(cls):
return [RIR, ]
def get_absolute_url(self):
return reverse('ipam:aggregate', args=[self.pk])

View File

@ -1,4 +1,3 @@
from django.apps import apps
from django.contrib.contenttypes.fields import GenericRelation, GenericForeignKey
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ValidationError
@ -95,6 +94,9 @@ class L2VPNTermination(NetBoxModel):
)
clone_fields = ('l2vpn',)
prerequisite_models = (
'ipam.L2VPN',
)
class Meta:
ordering = ('l2vpn',)
@ -111,10 +113,6 @@ class L2VPNTermination(NetBoxModel):
return f'{self.assigned_object} <> {self.l2vpn}'
return super().__str__()
@classmethod
def get_prerequisite_models(cls):
return [apps.get_model('ipam.L2VPN'), ]
def get_absolute_url(self):
return reverse('ipam:l2vpntermination', args=[self.pk])

View File

@ -3,9 +3,9 @@ from django.core.validators import ValidationError
from django.db import models
from mptt.models import MPTTModel, TreeForeignKey
from netbox.models.features import *
from utilities.mptt import TreeManager
from utilities.querysets import RestrictedQuerySet
from netbox.models.features import *
__all__ = (
'ChangeLoggedModel',
@ -33,14 +33,6 @@ class NetBoxFeatureSet(
def docs_url(self):
return f'{settings.STATIC_URL}docs/models/{self._meta.app_label}/{self._meta.model_name}/'
@classmethod
def get_prerequisite_models(cls):
"""
Return a list of model types that are required to create this model or empty list if none. This is used for
showing prerequisite warnings in the UI on the list and detail views.
"""
return []
#
# Base model classes

View File

@ -1,12 +1,13 @@
from django.apps import apps
def get_prerequisite_model(queryset):
model = queryset.model
"""
Return any prerequisite model that must be created prior to creating
an instance of the current model.
"""
if not queryset.exists():
if hasattr(model, 'get_prerequisite_models'):
prerequisites = model.get_prerequisite_models()
if prerequisites:
for prereq in prerequisites:
if not prereq.objects.exists():
return prereq
return None
for prereq in getattr(queryset.model, 'prerequisite_models', []):
model = apps.get_model(prereq)
if not model.objects.exists():
return model

View File

@ -94,6 +94,9 @@ class Cluster(PrimaryModel):
clone_fields = (
'type', 'group', 'status', 'tenant', 'site',
)
prerequisite_models = (
'virtualization.ClusterType',
)
class Meta:
ordering = ['name']
@ -111,10 +114,6 @@ class Cluster(PrimaryModel):
def __str__(self):
return self.name
@classmethod
def get_prerequisite_models(cls):
return [ClusterType, ]
def get_absolute_url(self):
return reverse('virtualization:cluster', args=[self.pk])

View File

@ -15,7 +15,6 @@ from utilities.fields import NaturalOrderingField
from utilities.ordering import naturalize_interface
from utilities.query_functions import CollateAsChar
from virtualization.choices import *
from .clusters import Cluster
__all__ = (
'VirtualMachine',
@ -131,6 +130,9 @@ class VirtualMachine(PrimaryModel, ConfigContextModel):
clone_fields = (
'site', 'cluster', 'device', 'tenant', 'platform', 'status', 'role', 'vcpus', 'memory', 'disk',
)
prerequisite_models = (
'virtualization.Cluster',
)
class Meta:
ordering = ('_name', 'pk') # Name may be non-unique
@ -150,10 +152,6 @@ class VirtualMachine(PrimaryModel, ConfigContextModel):
def __str__(self):
return self.name
@classmethod
def get_prerequisite_models(cls):
return [Cluster, ]
def get_absolute_url(self):
return reverse('virtualization:virtualmachine', args=[self.pk])

View File

@ -1,4 +1,3 @@
from django.apps import apps
from django.core.exceptions import ValidationError
from django.db import models
from django.urls import reverse
@ -193,10 +192,6 @@ class WirelessLink(WirelessAuthenticationBase, PrimaryModel):
def __str__(self):
return f'#{self.pk}'
@classmethod
def get_prerequisite_models(cls):
return [apps.get_model('dcim.Interface'), ]
def get_absolute_url(self):
return reverse('wireless:wirelesslink', args=[self.pk])