mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-22 20:12:00 -06:00
Rework template content registration to work like menu items
This commit is contained in:
parent
1d9fbeed81
commit
68a0e76ca6
@ -6,10 +6,10 @@ from django.template.loader import get_template
|
||||
from django.utils.module_loading import import_string
|
||||
|
||||
from extras.registry import registry
|
||||
from .signals import register_detail_page_content_classes
|
||||
|
||||
|
||||
# Initialize plugin registry stores
|
||||
registry['plugin_template_content_classes'] = collections.defaultdict(list)
|
||||
registry['plugin_nav_menu_links'] = {}
|
||||
|
||||
|
||||
@ -48,10 +48,18 @@ class PluginConfig(AppConfig):
|
||||
|
||||
# Default integration paths. Plugin authors can override these to customize the paths to
|
||||
# integrated components.
|
||||
template_content_classes = 'template_content.template_content_classes'
|
||||
menu_items = 'navigation.menu_items'
|
||||
|
||||
def ready(self):
|
||||
|
||||
# Register template content
|
||||
try:
|
||||
class_list = import_string(f"{self.__module__}.{self.template_content_classes}")
|
||||
register_template_content_classes(class_list)
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
# Register navigation menu items (if defined)
|
||||
try:
|
||||
menu_items = import_string(f"{self.__module__}.{self.menu_items}")
|
||||
@ -67,7 +75,7 @@ class PluginConfig(AppConfig):
|
||||
class PluginTemplateContent:
|
||||
"""
|
||||
This class is used to register plugin content to be injected into core NetBox templates.
|
||||
It contains methods that are overriden by plugin authors to return template content.
|
||||
It contains methods that are overridden by plugin authors to return template content.
|
||||
|
||||
The `model` attribute on the class defines the which model detail page this class renders
|
||||
content for. It should be set as a string in the form '<app_label>.<model_name>'.
|
||||
@ -123,36 +131,20 @@ class PluginTemplateContent:
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
def register_content_classes():
|
||||
def register_template_content_classes(class_list):
|
||||
"""
|
||||
Helper method that populates the registry with all template content classes that have been registered by plugins
|
||||
Register a list of PluginTemplateContent classes
|
||||
"""
|
||||
registry['plugin_template_content_classes'] = collections.defaultdict(list)
|
||||
# Validation
|
||||
for template_content_class in class_list:
|
||||
if not inspect.isclass(template_content_class):
|
||||
raise TypeError('Plugin content class {} was passes as an instance!'.format(template_content_class))
|
||||
if not issubclass(template_content_class, PluginTemplateContent):
|
||||
raise TypeError('{} is not a subclass of extras.plugins.PluginTemplateContent!'.format(template_content_class))
|
||||
if template_content_class.model is None:
|
||||
raise TypeError('Plugin content class {} does not define a valid model!'.format(template_content_class))
|
||||
|
||||
responses = register_detail_page_content_classes.send('registration_event')
|
||||
for receiver, response in responses:
|
||||
if not isinstance(response, list):
|
||||
response = [response]
|
||||
for template_class in response:
|
||||
if not inspect.isclass(template_class):
|
||||
raise TypeError('Plugin content class {} was passes as an instance!'.format(template_class))
|
||||
if not issubclass(template_class, PluginTemplateContent):
|
||||
raise TypeError('{} is not a subclass of extras.plugins.PluginTemplateContent!'.format(template_class))
|
||||
if template_class.model is None:
|
||||
raise TypeError('Plugin content class {} does not define a valid model!'.format(template_class))
|
||||
|
||||
registry['plugin_template_content_classes'][template_class.model].append(template_class)
|
||||
|
||||
|
||||
def get_content_classes(model):
|
||||
"""
|
||||
Given a model string, return the list of all registered template content classes.
|
||||
Populate the registry if it is empty.
|
||||
"""
|
||||
if 'plugin_template_content_classes' not in registry:
|
||||
register_content_classes()
|
||||
|
||||
return registry['plugin_template_content_classes'].get(model, [])
|
||||
registry['plugin_template_content_classes'][template_content_class.model].append(template_content_class)
|
||||
|
||||
|
||||
#
|
||||
|
@ -3,7 +3,9 @@ from django.dispatch.dispatcher import NO_RECEIVERS
|
||||
|
||||
|
||||
class PluginSignal(django.dispatch.Signal):
|
||||
|
||||
"""
|
||||
FUTURE USE
|
||||
"""
|
||||
def _sorted_receivers(self, sender):
|
||||
orig_list = self._live_receivers(sender)
|
||||
sorted_list = sorted(
|
||||
@ -24,11 +26,3 @@ class PluginSignal(django.dispatch.Signal):
|
||||
response = receiver(signal=self, sender=sender, **kwargs)
|
||||
responses.append((receiver, response))
|
||||
return responses
|
||||
|
||||
|
||||
"""
|
||||
This signal collects template content classes which render content for object detail pages
|
||||
"""
|
||||
register_detail_page_content_classes = PluginSignal(
|
||||
providing_args=[]
|
||||
)
|
||||
|
@ -1,9 +1,7 @@
|
||||
from django import template as template_
|
||||
from django.template.loader import get_template
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
from extras.plugins import get_content_classes
|
||||
|
||||
from extras.registry import registry
|
||||
|
||||
register = template_.Library()
|
||||
|
||||
@ -15,7 +13,8 @@ def _get_registered_content(obj, method, context):
|
||||
"""
|
||||
html = ''
|
||||
|
||||
plugin_template_classes = get_content_classes(obj._meta.label_lower)
|
||||
model_name = obj._meta.label_lower
|
||||
plugin_template_classes = registry['plugin_template_content_classes'].get(model_name, [])
|
||||
for plugin_template_class in plugin_template_classes:
|
||||
plugin_template_renderer = plugin_template_class(obj, context)
|
||||
try:
|
||||
|
Loading…
Reference in New Issue
Block a user