mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-22 20:12:00 -06:00
Revert "implemented registry for extras model functionality"
This reverts commit 235d99021b
.
This commit is contained in:
parent
6ea15cec6f
commit
2dc31c0edd
@ -21,7 +21,6 @@ from dcim.constants import *
|
||||
from dcim.fields import ASNField
|
||||
from dcim.elevations import RackElevationSVG
|
||||
from extras.models import ConfigContextModel, CustomFieldModel, ObjectChange, TaggedItem
|
||||
from extras.utils import extras_functionality
|
||||
from utilities.fields import ColorField, NaturalOrderingField
|
||||
from utilities.models import ChangeLoggedModel
|
||||
from utilities.utils import serialize_object, to_meters
|
||||
@ -1221,7 +1220,6 @@ class Platform(ChangeLoggedModel):
|
||||
)
|
||||
|
||||
|
||||
@extras_functionality(['webhooks', 'custom_fields', 'export_templates', 'custom_links', 'graphs'])
|
||||
class Device(ChangeLoggedModel, ConfigContextModel, CustomFieldModel):
|
||||
"""
|
||||
A Device represents a piece of physical hardware mounted within a Rack. Each Device is assigned a DeviceType,
|
||||
|
@ -1,6 +1,5 @@
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from django.db.models import Q
|
||||
from drf_yasg.utils import swagger_serializer_method
|
||||
from rest_framework import serializers
|
||||
|
||||
@ -14,7 +13,6 @@ from extras.constants import *
|
||||
from extras.models import (
|
||||
ConfigContext, ExportTemplate, Graph, ImageAttachment, ObjectChange, ReportResult, Tag,
|
||||
)
|
||||
from extras.utils import FunctionalityQueryset
|
||||
from tenancy.api.nested_serializers import NestedTenantSerializer, NestedTenantGroupSerializer
|
||||
from tenancy.models import Tenant, TenantGroup
|
||||
from users.api.nested_serializers import NestedUserSerializer
|
||||
@ -33,7 +31,7 @@ from .nested_serializers import *
|
||||
|
||||
class GraphSerializer(ValidatedModelSerializer):
|
||||
type = ContentTypeField(
|
||||
queryset=ContentType.objects.filter(FunctionalityQueryset('graphs').get_queryset()),
|
||||
queryset=ContentType.objects.filter(GRAPH_MODELS),
|
||||
)
|
||||
|
||||
class Meta:
|
||||
@ -69,7 +67,7 @@ class RenderedGraphSerializer(serializers.ModelSerializer):
|
||||
|
||||
class ExportTemplateSerializer(ValidatedModelSerializer):
|
||||
content_type = ContentTypeField(
|
||||
queryset=ContentType.objects.filter(Q(FunctionalityQueryset('export_templates').get_queryset())),
|
||||
queryset=ContentType.objects.filter(EXPORTTEMPLATE_MODELS),
|
||||
)
|
||||
template_language = ChoiceField(
|
||||
choices=TemplateLanguageChoices,
|
||||
|
@ -2,127 +2,127 @@ from django.db.models import Q
|
||||
|
||||
|
||||
# Models which support custom fields
|
||||
#CUSTOMFIELD_MODELS = Q(
|
||||
# Q(app_label='circuits', model__in=[
|
||||
# 'circuit',
|
||||
# 'provider',
|
||||
# ]) |
|
||||
# Q(app_label='dcim', model__in=[
|
||||
# 'device',
|
||||
# 'devicetype',
|
||||
# 'powerfeed',
|
||||
# 'rack',
|
||||
# 'site',
|
||||
# ]) |
|
||||
# Q(app_label='ipam', model__in=[
|
||||
# 'aggregate',
|
||||
# 'ipaddress',
|
||||
# 'prefix',
|
||||
# 'service',
|
||||
# 'vlan',
|
||||
# 'vrf',
|
||||
# ]) |
|
||||
# Q(app_label='secrets', model__in=[
|
||||
# 'secret',
|
||||
# ]) |
|
||||
# Q(app_label='tenancy', model__in=[
|
||||
# 'tenant',
|
||||
# ]) |
|
||||
# Q(app_label='virtualization', model__in=[
|
||||
# 'cluster',
|
||||
# 'virtualmachine',
|
||||
# ])
|
||||
#)
|
||||
#
|
||||
## Custom links
|
||||
#CUSTOMLINK_MODELS = Q(
|
||||
# Q(app_label='circuits', model__in=[
|
||||
# 'circuit',
|
||||
# 'provider',
|
||||
# ]) |
|
||||
# Q(app_label='dcim', model__in=[
|
||||
# 'cable',
|
||||
# 'device',
|
||||
# 'devicetype',
|
||||
# 'powerpanel',
|
||||
# 'powerfeed',
|
||||
# 'rack',
|
||||
# 'site',
|
||||
# ]) |
|
||||
# Q(app_label='ipam', model__in=[
|
||||
# 'aggregate',
|
||||
# 'ipaddress',
|
||||
# 'prefix',
|
||||
# 'service',
|
||||
# 'vlan',
|
||||
# 'vrf',
|
||||
# ]) |
|
||||
# Q(app_label='secrets', model__in=[
|
||||
# 'secret',
|
||||
# ]) |
|
||||
# Q(app_label='tenancy', model__in=[
|
||||
# 'tenant',
|
||||
# ]) |
|
||||
# Q(app_label='virtualization', model__in=[
|
||||
# 'cluster',
|
||||
# 'virtualmachine',
|
||||
# ])
|
||||
#)
|
||||
#
|
||||
## Models which can have Graphs associated with them
|
||||
#GRAPH_MODELS = Q(
|
||||
# Q(app_label='circuits', model__in=[
|
||||
# 'provider',
|
||||
# ]) |
|
||||
# Q(app_label='dcim', model__in=[
|
||||
# 'device',
|
||||
# 'interface',
|
||||
# 'site',
|
||||
# ])
|
||||
#)
|
||||
#
|
||||
## Models which support export templates
|
||||
#EXPORTTEMPLATE_MODELS = Q(
|
||||
# Q(app_label='circuits', model__in=[
|
||||
# 'circuit',
|
||||
# 'provider',
|
||||
# ]) |
|
||||
# Q(app_label='dcim', model__in=[
|
||||
# 'cable',
|
||||
# 'consoleport',
|
||||
# 'device',
|
||||
# 'devicetype',
|
||||
# 'interface',
|
||||
# 'inventoryitem',
|
||||
# 'manufacturer',
|
||||
# 'powerpanel',
|
||||
# 'powerport',
|
||||
# 'powerfeed',
|
||||
# 'rack',
|
||||
# 'rackgroup',
|
||||
# 'region',
|
||||
# 'site',
|
||||
# 'virtualchassis',
|
||||
# ]) |
|
||||
# Q(app_label='ipam', model__in=[
|
||||
# 'aggregate',
|
||||
# 'ipaddress',
|
||||
# 'prefix',
|
||||
# 'service',
|
||||
# 'vlan',
|
||||
# 'vrf',
|
||||
# ]) |
|
||||
# Q(app_label='secrets', model__in=[
|
||||
# 'secret',
|
||||
# ]) |
|
||||
# Q(app_label='tenancy', model__in=[
|
||||
# 'tenant',
|
||||
# ]) |
|
||||
# Q(app_label='virtualization', model__in=[
|
||||
# 'cluster',
|
||||
# 'virtualmachine',
|
||||
# ])
|
||||
#)
|
||||
CUSTOMFIELD_MODELS = Q(
|
||||
Q(app_label='circuits', model__in=[
|
||||
'circuit',
|
||||
'provider',
|
||||
]) |
|
||||
Q(app_label='dcim', model__in=[
|
||||
'device',
|
||||
'devicetype',
|
||||
'powerfeed',
|
||||
'rack',
|
||||
'site',
|
||||
]) |
|
||||
Q(app_label='ipam', model__in=[
|
||||
'aggregate',
|
||||
'ipaddress',
|
||||
'prefix',
|
||||
'service',
|
||||
'vlan',
|
||||
'vrf',
|
||||
]) |
|
||||
Q(app_label='secrets', model__in=[
|
||||
'secret',
|
||||
]) |
|
||||
Q(app_label='tenancy', model__in=[
|
||||
'tenant',
|
||||
]) |
|
||||
Q(app_label='virtualization', model__in=[
|
||||
'cluster',
|
||||
'virtualmachine',
|
||||
])
|
||||
)
|
||||
|
||||
# Custom links
|
||||
CUSTOMLINK_MODELS = Q(
|
||||
Q(app_label='circuits', model__in=[
|
||||
'circuit',
|
||||
'provider',
|
||||
]) |
|
||||
Q(app_label='dcim', model__in=[
|
||||
'cable',
|
||||
'device',
|
||||
'devicetype',
|
||||
'powerpanel',
|
||||
'powerfeed',
|
||||
'rack',
|
||||
'site',
|
||||
]) |
|
||||
Q(app_label='ipam', model__in=[
|
||||
'aggregate',
|
||||
'ipaddress',
|
||||
'prefix',
|
||||
'service',
|
||||
'vlan',
|
||||
'vrf',
|
||||
]) |
|
||||
Q(app_label='secrets', model__in=[
|
||||
'secret',
|
||||
]) |
|
||||
Q(app_label='tenancy', model__in=[
|
||||
'tenant',
|
||||
]) |
|
||||
Q(app_label='virtualization', model__in=[
|
||||
'cluster',
|
||||
'virtualmachine',
|
||||
])
|
||||
)
|
||||
|
||||
# Models which can have Graphs associated with them
|
||||
GRAPH_MODELS = Q(
|
||||
Q(app_label='circuits', model__in=[
|
||||
'provider',
|
||||
]) |
|
||||
Q(app_label='dcim', model__in=[
|
||||
'device',
|
||||
'interface',
|
||||
'site',
|
||||
])
|
||||
)
|
||||
|
||||
# Models which support export templates
|
||||
EXPORTTEMPLATE_MODELS = Q(
|
||||
Q(app_label='circuits', model__in=[
|
||||
'circuit',
|
||||
'provider',
|
||||
]) |
|
||||
Q(app_label='dcim', model__in=[
|
||||
'cable',
|
||||
'consoleport',
|
||||
'device',
|
||||
'devicetype',
|
||||
'interface',
|
||||
'inventoryitem',
|
||||
'manufacturer',
|
||||
'powerpanel',
|
||||
'powerport',
|
||||
'powerfeed',
|
||||
'rack',
|
||||
'rackgroup',
|
||||
'region',
|
||||
'site',
|
||||
'virtualchassis',
|
||||
]) |
|
||||
Q(app_label='ipam', model__in=[
|
||||
'aggregate',
|
||||
'ipaddress',
|
||||
'prefix',
|
||||
'service',
|
||||
'vlan',
|
||||
'vrf',
|
||||
]) |
|
||||
Q(app_label='secrets', model__in=[
|
||||
'secret',
|
||||
]) |
|
||||
Q(app_label='tenancy', model__in=[
|
||||
'tenant',
|
||||
]) |
|
||||
Q(app_label='virtualization', model__in=[
|
||||
'cluster',
|
||||
'virtualmachine',
|
||||
])
|
||||
)
|
||||
|
||||
# Report logging levels
|
||||
LOG_DEFAULT = 0
|
||||
@ -141,58 +141,48 @@ LOG_LEVEL_CODES = {
|
||||
HTTP_CONTENT_TYPE_JSON = 'application/json'
|
||||
|
||||
# Models which support registered webhooks
|
||||
#WEBHOOK_MODELS = Q(
|
||||
# Q(app_label='circuits', model__in=[
|
||||
# 'circuit',
|
||||
# 'provider',
|
||||
# ]) |
|
||||
# Q(app_label='dcim', model__in=[
|
||||
# 'cable',
|
||||
# 'consoleport',
|
||||
# 'consoleserverport',
|
||||
# 'device',
|
||||
# 'devicebay',
|
||||
# 'devicetype',
|
||||
# 'frontport',
|
||||
# 'interface',
|
||||
# 'inventoryitem',
|
||||
# 'manufacturer',
|
||||
# 'poweroutlet',
|
||||
# 'powerpanel',
|
||||
# 'powerport',
|
||||
# 'powerfeed',
|
||||
# 'rack',
|
||||
# 'rearport',
|
||||
# 'region',
|
||||
# 'site',
|
||||
# 'virtualchassis',
|
||||
# ]) |
|
||||
# Q(app_label='ipam', model__in=[
|
||||
# 'aggregate',
|
||||
# 'ipaddress',
|
||||
# 'prefix',
|
||||
# 'service',
|
||||
# 'vlan',
|
||||
# 'vrf',
|
||||
# ]) |
|
||||
# Q(app_label='secrets', model__in=[
|
||||
# 'secret',
|
||||
# ]) |
|
||||
# Q(app_label='tenancy', model__in=[
|
||||
# 'tenant',
|
||||
# ]) |
|
||||
# Q(app_label='virtualization', model__in=[
|
||||
# 'cluster',
|
||||
# 'virtualmachine',
|
||||
# ])
|
||||
#)
|
||||
|
||||
|
||||
# Registerable extras functionalities
|
||||
EXTRAS_FUNCTIONALITIES = [
|
||||
'custom_fields',
|
||||
'custom_links',
|
||||
'graphs',
|
||||
'export_templates',
|
||||
'webhooks'
|
||||
]
|
||||
WEBHOOK_MODELS = Q(
|
||||
Q(app_label='circuits', model__in=[
|
||||
'circuit',
|
||||
'provider',
|
||||
]) |
|
||||
Q(app_label='dcim', model__in=[
|
||||
'cable',
|
||||
'consoleport',
|
||||
'consoleserverport',
|
||||
'device',
|
||||
'devicebay',
|
||||
'devicetype',
|
||||
'frontport',
|
||||
'interface',
|
||||
'inventoryitem',
|
||||
'manufacturer',
|
||||
'poweroutlet',
|
||||
'powerpanel',
|
||||
'powerport',
|
||||
'powerfeed',
|
||||
'rack',
|
||||
'rearport',
|
||||
'region',
|
||||
'site',
|
||||
'virtualchassis',
|
||||
]) |
|
||||
Q(app_label='ipam', model__in=[
|
||||
'aggregate',
|
||||
'ipaddress',
|
||||
'prefix',
|
||||
'service',
|
||||
'vlan',
|
||||
'vrf',
|
||||
]) |
|
||||
Q(app_label='secrets', model__in=[
|
||||
'secret',
|
||||
]) |
|
||||
Q(app_label='tenancy', model__in=[
|
||||
'tenant',
|
||||
]) |
|
||||
Q(app_label='virtualization', model__in=[
|
||||
'cluster',
|
||||
'virtualmachine',
|
||||
])
|
||||
)
|
||||
|
@ -22,7 +22,6 @@ from utilities.utils import deepmerge, render_jinja2
|
||||
from .choices import *
|
||||
from .constants import *
|
||||
from .querysets import ConfigContextQuerySet
|
||||
from .utils import FunctionalityQueryset
|
||||
|
||||
|
||||
__all__ = (
|
||||
@ -59,7 +58,7 @@ class Webhook(models.Model):
|
||||
to=ContentType,
|
||||
related_name='webhooks',
|
||||
verbose_name='Object types',
|
||||
limit_choices_to=FunctionalityQueryset('webhooks'),
|
||||
limit_choices_to=WEBHOOK_MODELS,
|
||||
help_text="The object(s) to which this Webhook applies."
|
||||
)
|
||||
name = models.CharField(
|
||||
@ -224,7 +223,7 @@ class CustomField(models.Model):
|
||||
to=ContentType,
|
||||
related_name='custom_fields',
|
||||
verbose_name='Object(s)',
|
||||
limit_choices_to=FunctionalityQueryset('custom_fields'),
|
||||
limit_choices_to=CUSTOMFIELD_MODELS,
|
||||
help_text='The object(s) to which this field applies.'
|
||||
)
|
||||
type = models.CharField(
|
||||
@ -471,7 +470,7 @@ class CustomLink(models.Model):
|
||||
content_type = models.ForeignKey(
|
||||
to=ContentType,
|
||||
on_delete=models.CASCADE,
|
||||
limit_choices_to=FunctionalityQueryset('custom_links')
|
||||
limit_choices_to=CUSTOMLINK_MODELS
|
||||
)
|
||||
name = models.CharField(
|
||||
max_length=100,
|
||||
@ -519,7 +518,7 @@ class Graph(models.Model):
|
||||
type = models.ForeignKey(
|
||||
to=ContentType,
|
||||
on_delete=models.CASCADE,
|
||||
limit_choices_to=FunctionalityQueryset('graphs')
|
||||
limit_choices_to=GRAPH_MODELS
|
||||
)
|
||||
weight = models.PositiveSmallIntegerField(
|
||||
default=1000
|
||||
@ -582,7 +581,7 @@ class ExportTemplate(models.Model):
|
||||
content_type = models.ForeignKey(
|
||||
to=ContentType,
|
||||
on_delete=models.CASCADE,
|
||||
limit_choices_to=FunctionalityQueryset('export_templates')
|
||||
limit_choices_to=EXPORTTEMPLATE_MODELS
|
||||
)
|
||||
name = models.CharField(
|
||||
max_length=100
|
||||
|
@ -1,11 +1,6 @@
|
||||
import collections
|
||||
|
||||
from django.db.models import Q
|
||||
from taggit.managers import _TaggableManager
|
||||
from utilities.querysets import DummyQuerySet
|
||||
|
||||
from extras.constants import EXTRAS_FUNCTIONALITIES
|
||||
|
||||
|
||||
def is_taggable(obj):
|
||||
"""
|
||||
@ -18,59 +13,3 @@ def is_taggable(obj):
|
||||
if isinstance(obj.tags, DummyQuerySet):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
class Registry:
|
||||
"""
|
||||
Singleton object used to store important data
|
||||
"""
|
||||
instance = None
|
||||
|
||||
def __new__(cls):
|
||||
if cls.instance is not None:
|
||||
return cls.instance
|
||||
else:
|
||||
cls.instance = super().__new__(cls)
|
||||
cls.model_functionality_store = {f: collections.defaultdict(list) for f in EXTRAS_FUNCTIONALITIES}
|
||||
return cls.instance
|
||||
|
||||
|
||||
class FunctionalityQueryset:
|
||||
"""
|
||||
Helper class that delays evaluation of the registry contents for the functionaility store
|
||||
until it has been populated.
|
||||
"""
|
||||
|
||||
def __init__(self, functionality):
|
||||
self.functionality = functionality
|
||||
|
||||
def __call__(self):
|
||||
return self.get_queryset()
|
||||
|
||||
def get_queryset(self):
|
||||
"""
|
||||
Given an extras functionality, return a Q object for content type lookup
|
||||
"""
|
||||
query = Q()
|
||||
registry = Registry()
|
||||
for app_label, models in registry.model_functionality_store[self.functionality].items():
|
||||
query |= Q(app_label=app_label, model__in=models)
|
||||
|
||||
return query
|
||||
|
||||
|
||||
def extras_functionality(functionalities):
|
||||
"""
|
||||
Decorator used to register extras provided functionalities to a model
|
||||
"""
|
||||
def wrapper(model_class):
|
||||
if isinstance(functionalities, list) and functionalities:
|
||||
registry = Registry()
|
||||
model_class._extras_functionality = []
|
||||
for functionality in functionalities:
|
||||
if functionality in EXTRAS_FUNCTIONALITIES:
|
||||
model_class._extras_functionality.append(functionality)
|
||||
app_label, model_name = model_class._meta.label_lower.split('.')
|
||||
registry.model_functionality_store[functionality][app_label].append(model_name)
|
||||
return model_class
|
||||
return wrapper
|
||||
|
Loading…
Reference in New Issue
Block a user