Przeglądaj źródła

Closes #18211: Enable dynamic registration of request processors (#18212)

* Closes #18211: Enable dynamic registration of request processors

* Tweak syntax
Jeremy Stretch 1 rok temu
rodzic
commit
8e427e57ea

+ 4 - 0
docs/development/application-registry.md

@@ -49,6 +49,10 @@ This key lists all models which have been registered in NetBox which are not des
 
 This store maintains all registered items for plugins, such as navigation menus, template extensions, etc.
 
+### `request_processors`
+
+A list of context managers to invoke when processing a request e.g. in middleware or when executing a background job. Request processors can be registered with the `@register_request_processor` decorator.
+
 ### `search`
 
 A dictionary mapping each model (identified by its app and label) to its search index class, if one has been registered for it.

+ 2 - 0
netbox/netbox/context_managers.py

@@ -1,9 +1,11 @@
 from contextlib import contextmanager
 
 from netbox.context import current_request, events_queue
+from netbox.utils import register_request_processor
 from extras.events import flush_events
 
 
+@register_request_processor
 @contextmanager
 def event_tracking(request):
     """

+ 7 - 3
netbox/netbox/middleware.py

@@ -1,3 +1,5 @@
+from contextlib import ExitStack
+
 import logging
 import uuid
 
@@ -10,7 +12,7 @@ from django.db.utils import InternalError
 from django.http import Http404, HttpResponseRedirect
 
 from netbox.config import clear_config, get_config
-from netbox.context_managers import event_tracking
+from netbox.registry import registry
 from netbox.views import handler_500
 from utilities.api import is_api_request
 from utilities.error_handlers import handle_rest_api_exception
@@ -32,8 +34,10 @@ class CoreMiddleware:
         # Assign a random unique ID to the request. This will be used for change logging.
         request.id = uuid.uuid4()
 
-        # Enable the event_tracking context manager and process the request.
-        with event_tracking(request):
+        # Apply all registered request processors
+        with ExitStack() as stack:
+            for request_processor in registry['request_processors']:
+                stack.enter_context(request_processor(request))
             response = self.get_response(request)
 
         # Check if language cookie should be renewed

+ 1 - 0
netbox/netbox/registry.py

@@ -29,6 +29,7 @@ registry = Registry({
     'model_features': dict(),
     'models': collections.defaultdict(set),
     'plugins': dict(),
+    'request_processors': list(),
     'search': dict(),
     'tables': collections.defaultdict(dict),
     'views': collections.defaultdict(dict),

+ 10 - 0
netbox/netbox/utils.py

@@ -3,6 +3,7 @@ from netbox.registry import registry
 __all__ = (
     'get_data_backend_choices',
     'register_data_backend',
+    'register_request_processor',
 )
 
 
@@ -24,3 +25,12 @@ def register_data_backend():
         return cls
 
     return _wrapper
+
+
+def register_request_processor(func):
+    """
+    Decorator for registering a request processor.
+    """
+    registry['request_processors'].append(func)
+
+    return func