Skip to content

Commit

Permalink
Use strings to specify prerequisite models
Browse files Browse the repository at this point in the history
  • Loading branch information
jeremystretch committed Nov 16, 2022
1 parent f411c4f commit ebf555e
Show file tree
Hide file tree
Showing 12 changed files with 61 additions and 86 deletions.
8 changes: 4 additions & 4 deletions netbox/circuits/models/circuits.py
Original file line number Diff line number Diff line change
Expand Up @@ -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']
Expand All @@ -117,10 +121,6 @@ class Meta:
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])

Expand Down
23 changes: 11 additions & 12 deletions netbox/dcim/models/devices.py
Original file line number Diff line number Diff line change
Expand Up @@ -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']
Expand Down Expand Up @@ -151,10 +154,6 @@ def __init__(self, *args, **kwargs):
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])

Expand Down Expand Up @@ -325,6 +324,9 @@ class ModuleType(PrimaryModel, WeightMixin):
)

clone_fields = ('manufacturer', 'weight', 'weight_unit',)
prerequisite_models = (
'dcim.Manufacturer',
)

class Meta:
ordering = ('manufacturer', 'model')
Expand All @@ -338,10 +340,6 @@ class Meta:
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])

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -638,10 +641,6 @@ def __str__(self):
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])

Expand Down
16 changes: 7 additions & 9 deletions netbox/dcim/models/power.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -48,6 +47,10 @@ class PowerPanel(PrimaryModel):
to='extras.ImageAttachment'
)

prerequisite_models = (
'dcim.Site',
)

class Meta:
ordering = ['site', 'name']
constraints = (
Expand All @@ -60,10 +63,6 @@ class Meta:
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])

Expand Down Expand Up @@ -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']
Expand All @@ -150,10 +152,6 @@ class Meta:
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])

Expand Down
16 changes: 7 additions & 9 deletions netbox/dcim/models/racks.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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
Expand All @@ -197,10 +199,6 @@ def __str__(self):
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])

Expand Down Expand Up @@ -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])

Expand Down
7 changes: 3 additions & 4 deletions netbox/dcim/models/sites.py
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,9 @@ class Location(NestedGroupModel):
)

clone_fields = ('site', 'parent', 'status', 'tenant', 'description')
prerequisite_models = (
'dcim.Site',
)

class Meta:
ordering = ['site', 'name']
Expand All @@ -312,10 +315,6 @@ class Meta:
),
)

@classmethod
def get_prerequisite_models(cls):
return [Site, ]

def get_absolute_url(self):
return reverse('dcim:location', args=[self.pk])

Expand Down
18 changes: 8 additions & 10 deletions netbox/ipam/models/ip.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,16 @@

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
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',
Expand Down Expand Up @@ -101,6 +100,10 @@ class ASN(PrimaryModel):
null=True
)

prerequisite_models = (
'ipam.RIR',
)

class Meta:
ordering = ['asn']
verbose_name = 'ASN'
Expand All @@ -109,10 +112,6 @@ class Meta:
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])

Expand Down Expand Up @@ -163,17 +162,16 @@ 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

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])

Expand Down
8 changes: 3 additions & 5 deletions netbox/ipam/models/l2vpn.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -95,6 +94,9 @@ class L2VPNTermination(NetBoxModel):
)

clone_fields = ('l2vpn',)
prerequisite_models = (
'ipam.L2VPN',
)

class Meta:
ordering = ('l2vpn',)
Expand All @@ -111,10 +113,6 @@ def __str__(self):
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])

Expand Down
10 changes: 1 addition & 9 deletions netbox/netbox/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
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',
Expand Down Expand Up @@ -33,14 +33,6 @@ class Meta:
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
Expand Down
21 changes: 11 additions & 10 deletions netbox/netbox/views/generic/utils.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
def get_prerequisite_model(queryset):
model = queryset.model
from django.apps import apps

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
def get_prerequisite_model(queryset):
"""
Return any prerequisite model that must be created prior to creating
an instance of the current model.
"""
if not queryset.exists():
for prereq in getattr(queryset.model, 'prerequisite_models', []):
model = apps.get_model(prereq)
if not model.objects.exists():
return model
7 changes: 3 additions & 4 deletions netbox/virtualization/models/clusters.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ class Cluster(PrimaryModel):
clone_fields = (
'type', 'group', 'status', 'tenant', 'site',
)
prerequisite_models = (
'virtualization.ClusterType',
)

class Meta:
ordering = ['name']
Expand All @@ -111,10 +114,6 @@ class Meta:
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])

Expand Down
8 changes: 3 additions & 5 deletions netbox/virtualization/models/virtualmachines.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
from utilities.ordering import naturalize_interface
from utilities.query_functions import CollateAsChar
from virtualization.choices import *
from .clusters import Cluster

__all__ = (
'VirtualMachine',
Expand Down Expand Up @@ -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
Expand All @@ -150,10 +152,6 @@ class Meta:
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])

Expand Down
Loading

0 comments on commit ebf555e

Please sign in to comment.