mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-16 04:02:52 -06:00
* Closes #15042: Move model registration logic to AppConfigs * Refactor register_model() to accept multiple models
This commit is contained in:
parent
7abb2b2ab5
commit
5f159795dd
@ -6,4 +6,8 @@ class CircuitsConfig(AppConfig):
|
|||||||
verbose_name = "Circuits"
|
verbose_name = "Circuits"
|
||||||
|
|
||||||
def ready(self):
|
def ready(self):
|
||||||
|
from netbox.models.features import register_models
|
||||||
from . import signals, search
|
from . import signals, search
|
||||||
|
|
||||||
|
# Register models
|
||||||
|
register_models(*self.get_models())
|
||||||
|
@ -16,5 +16,9 @@ class CoreConfig(AppConfig):
|
|||||||
name = "core"
|
name = "core"
|
||||||
|
|
||||||
def ready(self):
|
def ready(self):
|
||||||
|
from core.api import schema # noqa
|
||||||
|
from netbox.models.features import register_models
|
||||||
from . import data_backends, search
|
from . import data_backends, search
|
||||||
from core.api import schema # noqa: E402
|
|
||||||
|
# Register models
|
||||||
|
register_models(*self.get_models())
|
||||||
|
@ -8,9 +8,13 @@ class DCIMConfig(AppConfig):
|
|||||||
verbose_name = "DCIM"
|
verbose_name = "DCIM"
|
||||||
|
|
||||||
def ready(self):
|
def ready(self):
|
||||||
|
from netbox.models.features import register_models
|
||||||
|
from utilities.counters import connect_counters
|
||||||
from . import signals, search
|
from . import signals, search
|
||||||
from .models import CableTermination, Device, DeviceType, VirtualChassis
|
from .models import CableTermination, Device, DeviceType, VirtualChassis
|
||||||
from utilities.counters import connect_counters
|
|
||||||
|
# Register models
|
||||||
|
register_models(*self.get_models())
|
||||||
|
|
||||||
# Register denormalized fields
|
# Register denormalized fields
|
||||||
denormalized.register(CableTermination, '_device', {
|
denormalized.register(CableTermination, '_device', {
|
||||||
|
@ -5,4 +5,8 @@ class ExtrasConfig(AppConfig):
|
|||||||
name = "extras"
|
name = "extras"
|
||||||
|
|
||||||
def ready(self):
|
def ready(self):
|
||||||
|
from netbox.models.features import register_models
|
||||||
from . import dashboard, lookups, search, signals
|
from . import dashboard, lookups, search, signals
|
||||||
|
|
||||||
|
# Register models
|
||||||
|
register_models(*self.get_models())
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
from taggit.managers import _TaggableManager
|
from taggit.managers import _TaggableManager
|
||||||
|
|
||||||
from netbox.registry import registry
|
|
||||||
|
|
||||||
|
|
||||||
def is_taggable(obj):
|
def is_taggable(obj):
|
||||||
"""
|
"""
|
||||||
@ -29,24 +27,6 @@ def image_upload(instance, filename):
|
|||||||
return '{}{}_{}_{}'.format(path, instance.content_type.name, instance.object_id, filename)
|
return '{}{}_{}_{}'.format(path, instance.content_type.name, instance.object_id, filename)
|
||||||
|
|
||||||
|
|
||||||
def register_features(model, features):
|
|
||||||
"""
|
|
||||||
Register model features in the application registry.
|
|
||||||
"""
|
|
||||||
app_label, model_name = model._meta.label_lower.split('.')
|
|
||||||
for feature in features:
|
|
||||||
try:
|
|
||||||
registry['model_features'][feature][app_label].add(model_name)
|
|
||||||
except KeyError:
|
|
||||||
raise KeyError(
|
|
||||||
f"{feature} is not a valid model feature! Valid keys are: {registry['model_features'].keys()}"
|
|
||||||
)
|
|
||||||
|
|
||||||
# Register public models
|
|
||||||
if not getattr(model, '_netbox_private', False):
|
|
||||||
registry['models'][app_label].add(model_name)
|
|
||||||
|
|
||||||
|
|
||||||
def is_script(obj):
|
def is_script(obj):
|
||||||
"""
|
"""
|
||||||
Returns True if the object is a Script or Report.
|
Returns True if the object is a Script or Report.
|
||||||
|
@ -6,4 +6,8 @@ class IPAMConfig(AppConfig):
|
|||||||
verbose_name = "IPAM"
|
verbose_name = "IPAM"
|
||||||
|
|
||||||
def ready(self):
|
def ready(self):
|
||||||
|
from netbox.models.features import register_models
|
||||||
from . import signals, search
|
from . import signals, search
|
||||||
|
|
||||||
|
# Register models
|
||||||
|
register_models(*self.get_models())
|
||||||
|
@ -5,8 +5,6 @@ from functools import cached_property
|
|||||||
from django.contrib.contenttypes.fields import GenericRelation
|
from django.contrib.contenttypes.fields import GenericRelation
|
||||||
from django.core.validators import ValidationError
|
from django.core.validators import ValidationError
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.db.models.signals import class_prepared
|
|
||||||
from django.dispatch import receiver
|
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from taggit.managers import TaggableManager
|
from taggit.managers import TaggableManager
|
||||||
@ -14,7 +12,7 @@ from taggit.managers import TaggableManager
|
|||||||
from core.choices import JobStatusChoices
|
from core.choices import JobStatusChoices
|
||||||
from core.models import ContentType
|
from core.models import ContentType
|
||||||
from extras.choices import *
|
from extras.choices import *
|
||||||
from extras.utils import is_taggable, register_features
|
from extras.utils import is_taggable
|
||||||
from netbox.config import get_config
|
from netbox.config import get_config
|
||||||
from netbox.registry import registry
|
from netbox.registry import registry
|
||||||
from netbox.signals import post_clean
|
from netbox.signals import post_clean
|
||||||
@ -37,6 +35,7 @@ __all__ = (
|
|||||||
'JournalingMixin',
|
'JournalingMixin',
|
||||||
'SyncedDataMixin',
|
'SyncedDataMixin',
|
||||||
'TagsMixin',
|
'TagsMixin',
|
||||||
|
'register_models',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -576,36 +575,49 @@ registry['model_features'].update({
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
@receiver(class_prepared)
|
def register_models(*models):
|
||||||
def _register_features(sender, **kwargs):
|
"""
|
||||||
# Record each applicable feature for the model in the registry
|
Register one or more models in NetBox. This entails:
|
||||||
features = {
|
|
||||||
feature for feature, cls in FEATURES_MAP.items() if issubclass(sender, cls)
|
|
||||||
}
|
|
||||||
register_features(sender, features)
|
|
||||||
|
|
||||||
# Register applicable feature views for the model
|
- Determining whether the model is considered "public" (available for reference by other models)
|
||||||
if issubclass(sender, JournalingMixin):
|
- Registering which features the model supports (e.g. bookmarks, custom fields, etc.)
|
||||||
register_model_view(
|
- Registering any feature-specific views for the model (e.g. ObjectJournalView instances)
|
||||||
sender,
|
|
||||||
'journal',
|
register_model() should be called for each relevant model under the ready() of an app's AppConfig class.
|
||||||
kwargs={'model': sender}
|
"""
|
||||||
)('netbox.views.generic.ObjectJournalView')
|
for model in models:
|
||||||
if issubclass(sender, ChangeLoggingMixin):
|
app_label, model_name = model._meta.label_lower.split('.')
|
||||||
register_model_view(
|
|
||||||
sender,
|
# Register public models
|
||||||
'changelog',
|
if not getattr(model, '_netbox_private', False):
|
||||||
kwargs={'model': sender}
|
registry['models'][app_label].add(model_name)
|
||||||
)('netbox.views.generic.ObjectChangeLogView')
|
|
||||||
if issubclass(sender, JobsMixin):
|
# Record each applicable feature for the model in the registry
|
||||||
register_model_view(
|
features = {
|
||||||
sender,
|
feature for feature, cls in FEATURES_MAP.items() if issubclass(model, cls)
|
||||||
'jobs',
|
}
|
||||||
kwargs={'model': sender}
|
for feature in features:
|
||||||
)('netbox.views.generic.ObjectJobsView')
|
try:
|
||||||
if issubclass(sender, SyncedDataMixin):
|
registry['model_features'][feature][app_label].add(model_name)
|
||||||
register_model_view(
|
except KeyError:
|
||||||
sender,
|
raise KeyError(
|
||||||
'sync',
|
f"{feature} is not a valid model feature! Valid keys are: {registry['model_features'].keys()}"
|
||||||
kwargs={'model': sender}
|
)
|
||||||
)('netbox.views.generic.ObjectSyncDataView')
|
|
||||||
|
# Register applicable feature views for the model
|
||||||
|
if issubclass(model, JournalingMixin):
|
||||||
|
register_model_view(model, 'journal', kwargs={'model': model})(
|
||||||
|
'netbox.views.generic.ObjectJournalView'
|
||||||
|
)
|
||||||
|
if issubclass(model, ChangeLoggingMixin):
|
||||||
|
register_model_view(model, 'changelog', kwargs={'model': model})(
|
||||||
|
'netbox.views.generic.ObjectChangeLogView'
|
||||||
|
)
|
||||||
|
if issubclass(model, JobsMixin):
|
||||||
|
register_model_view(model, 'jobs', kwargs={'model': model})(
|
||||||
|
'netbox.views.generic.ObjectJobsView'
|
||||||
|
)
|
||||||
|
if issubclass(model, SyncedDataMixin):
|
||||||
|
register_model_view(model, 'sync', kwargs={'model': model})(
|
||||||
|
'netbox.views.generic.ObjectSyncDataView'
|
||||||
|
)
|
||||||
|
@ -94,6 +94,11 @@ class PluginConfig(AppConfig):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def ready(self):
|
def ready(self):
|
||||||
|
from netbox.models.features import register_models
|
||||||
|
|
||||||
|
# Register models
|
||||||
|
register_models(*self.get_models())
|
||||||
|
|
||||||
plugin_name = self.name.rsplit('.', 1)[-1]
|
plugin_name = self.name.rsplit('.', 1)[-1]
|
||||||
|
|
||||||
# Register search extensions (if defined)
|
# Register search extensions (if defined)
|
||||||
|
@ -20,6 +20,10 @@ class PluginTest(TestCase):
|
|||||||
|
|
||||||
self.assertIn('netbox.tests.dummy_plugin.DummyPluginConfig', settings.INSTALLED_APPS)
|
self.assertIn('netbox.tests.dummy_plugin.DummyPluginConfig', settings.INSTALLED_APPS)
|
||||||
|
|
||||||
|
def test_model_registration(self):
|
||||||
|
self.assertIn('dummy_plugin', registry['models'])
|
||||||
|
self.assertIn('dummymodel', registry['models']['dummy_plugin'])
|
||||||
|
|
||||||
def test_models(self):
|
def test_models(self):
|
||||||
from netbox.tests.dummy_plugin.models import DummyModel
|
from netbox.tests.dummy_plugin.models import DummyModel
|
||||||
|
|
||||||
|
@ -5,4 +5,8 @@ class TenancyConfig(AppConfig):
|
|||||||
name = 'tenancy'
|
name = 'tenancy'
|
||||||
|
|
||||||
def ready(self):
|
def ready(self):
|
||||||
|
from netbox.models.features import register_models
|
||||||
from . import search
|
from . import search
|
||||||
|
|
||||||
|
# Register models
|
||||||
|
register_models(*self.get_models())
|
||||||
|
@ -5,15 +5,8 @@ class UsersConfig(AppConfig):
|
|||||||
name = 'users'
|
name = 'users'
|
||||||
|
|
||||||
def ready(self):
|
def ready(self):
|
||||||
import users.signals
|
from netbox.models.features import register_models
|
||||||
from .models import NetBoxGroup, ObjectPermission, Token, User, UserConfig
|
from . import signals
|
||||||
from netbox.models.features import _register_features
|
|
||||||
|
|
||||||
# have to register these manually as the signal handler for class_prepared does
|
# Register models
|
||||||
# not get registered until after these models are loaded. Any models defined in
|
register_models(*self.get_models())
|
||||||
# users.models should be registered here.
|
|
||||||
_register_features(NetBoxGroup)
|
|
||||||
_register_features(ObjectPermission)
|
|
||||||
_register_features(Token)
|
|
||||||
_register_features(User)
|
|
||||||
_register_features(UserConfig)
|
|
||||||
|
@ -7,9 +7,13 @@ class VirtualizationConfig(AppConfig):
|
|||||||
name = 'virtualization'
|
name = 'virtualization'
|
||||||
|
|
||||||
def ready(self):
|
def ready(self):
|
||||||
|
from netbox.models.features import register_models
|
||||||
|
from utilities.counters import connect_counters
|
||||||
from . import search, signals
|
from . import search, signals
|
||||||
from .models import VirtualMachine
|
from .models import VirtualMachine
|
||||||
from utilities.counters import connect_counters
|
|
||||||
|
# Register models
|
||||||
|
register_models(*self.get_models())
|
||||||
|
|
||||||
# Register denormalized fields
|
# Register denormalized fields
|
||||||
denormalized.register(VirtualMachine, 'cluster', {
|
denormalized.register(VirtualMachine, 'cluster', {
|
||||||
|
@ -6,4 +6,8 @@ class VPNConfig(AppConfig):
|
|||||||
verbose_name = 'VPN'
|
verbose_name = 'VPN'
|
||||||
|
|
||||||
def ready(self):
|
def ready(self):
|
||||||
|
from netbox.models.features import register_models
|
||||||
from . import search
|
from . import search
|
||||||
|
|
||||||
|
# Register models
|
||||||
|
register_models(*self.get_models())
|
||||||
|
@ -5,4 +5,8 @@ class WirelessConfig(AppConfig):
|
|||||||
name = 'wireless'
|
name = 'wireless'
|
||||||
|
|
||||||
def ready(self):
|
def ready(self):
|
||||||
|
from netbox.models.features import register_models
|
||||||
from . import signals, search
|
from . import signals, search
|
||||||
|
|
||||||
|
# Register models
|
||||||
|
register_models(*self.get_models())
|
||||||
|
Loading…
Reference in New Issue
Block a user