Просмотр исходного кода

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

* Closes #18211: Enable dynamic registration of request processors

* Tweak syntax
Jeremy Stretch 1 год назад
Родитель
Сommit
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.
 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`
 ### `search`
 
 
 A dictionary mapping each model (identified by its app and label) to its search index class, if one has been registered for it.
 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 contextlib import contextmanager
 
 
 from netbox.context import current_request, events_queue
 from netbox.context import current_request, events_queue
+from netbox.utils import register_request_processor
 from extras.events import flush_events
 from extras.events import flush_events
 
 
 
 
+@register_request_processor
 @contextmanager
 @contextmanager
 def event_tracking(request):
 def event_tracking(request):
     """
     """

+ 7 - 3
netbox/netbox/middleware.py

@@ -1,3 +1,5 @@
+from contextlib import ExitStack
+
 import logging
 import logging
 import uuid
 import uuid
 
 
@@ -10,7 +12,7 @@ from django.db.utils import InternalError
 from django.http import Http404, HttpResponseRedirect
 from django.http import Http404, HttpResponseRedirect
 
 
 from netbox.config import clear_config, get_config
 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 netbox.views import handler_500
 from utilities.api import is_api_request
 from utilities.api import is_api_request
 from utilities.error_handlers import handle_rest_api_exception
 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.
         # Assign a random unique ID to the request. This will be used for change logging.
         request.id = uuid.uuid4()
         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)
             response = self.get_response(request)
 
 
         # Check if language cookie should be renewed
         # Check if language cookie should be renewed

+ 1 - 0
netbox/netbox/registry.py

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

+ 10 - 0
netbox/netbox/utils.py

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