Code

Ticket #730: explicit_middleware_ordering_t730_r8166_v2.diff

File explicit_middleware_ordering_t730_r8166_v2.diff, 4.6 KB (added by andrewbadr, 6 years ago)
Line 
1Index: django/core/handlers/base.py
2===================================================================
3--- django/core/handlers/base.py        (revision 8166)
4+++ django/core/handlers/base.py        (working copy)
5@@ -17,6 +17,25 @@
6     def __init__(self):
7         self._request_middleware = self._view_middleware = self._response_middleware = self._exception_middleware = None
8 
9+    def middleware_class_from_path(middleware_path):
10+        from django.core import exceptions
11+        try:
12+            dot = middleware_path.rindex('.')
13+        except ValueError:
14+            raise exceptions.ImproperlyConfigured, '%s isn\'t a middleware module' % middleware_path
15+        mw_module, mw_classname = middleware_path[:dot], middleware_path[dot+1:]
16+        try:
17+            mod = __import__(mw_module, {}, {}, [''])
18+        except ImportError, e:
19+            raise exceptions.ImproperlyConfigured, 'Error importing middleware %s: "%s"' % (mw_module, e)
20+        try:
21+            mw_class = getattr(mod, mw_classname)
22+        except AttributeError:
23+            raise exceptions.ImproperlyConfigured, 'Middleware module "%s" does not define a "%s" class' % (mw_module, mw_classname)
24+        return mw_class
25+    middleware_class_from_path = staticmethod(middleware_class_from_path)
26+
27+
28     def load_middleware(self):
29         """
30         Populate middleware lists from settings.MIDDLEWARE_CLASSES.
31@@ -29,34 +48,42 @@
32         self._view_middleware = []
33         self._response_middleware = []
34         self._exception_middleware = []
35-        for middleware_path in settings.MIDDLEWARE_CLASSES:
36-            try:
37-                dot = middleware_path.rindex('.')
38-            except ValueError:
39-                raise exceptions.ImproperlyConfigured, '%s isn\'t a middleware module' % middleware_path
40-            mw_module, mw_classname = middleware_path[:dot], middleware_path[dot+1:]
41-            try:
42-                mod = __import__(mw_module, {}, {}, [''])
43-            except ImportError, e:
44-                raise exceptions.ImproperlyConfigured, 'Error importing middleware %s: "%s"' % (mw_module, e)
45-            try:
46-                mw_class = getattr(mod, mw_classname)
47-            except AttributeError:
48-                raise exceptions.ImproperlyConfigured, 'Middleware module "%s" does not define a "%s" class' % (mw_module, mw_classname)
49+       
50 
51+        # Get incoming and outgoing middleware orders and make sure they contain the same paths
52+        incoming_middleware_order = settings.MIDDLEWARE_CLASSES
53+        outgoing_middleware_order = getattr(settings, 'OUTBOUND_MIDDLEWARE_ORDER', None)
54+        if outgoing_middleware_order:
55+            if not len(incoming_middleware_order) == len(outgoing_middleware_order):
56+                raise exceptions.ImproperlyConfigured, 'OUTBOUND_MIDDLEWARE_ORDER must contain the same middleware as MIDDLEWARE_CLASSES'
57+            for middleware_path in incoming_middleware_order:
58+                if not middleware_path in outgoing_middleware_order:
59+                    raise exceptions.ImproperlyConfigured, 'OUTBOUND_MIDDLEWARE_ORDER does not contain %s MIDDLEWARE_CLASSES' % middleware_path
60+        else:
61+            outgoing_middleware_order = list(incoming_middleware_order)
62+            outgoing_middleware_order.reverse()
63+       
64+        instances = {}
65+        for middleware_path in incoming_middleware_order:
66+            mw_class = self.middleware_class_from_path(middleware_path)
67             try:
68                 mw_instance = mw_class()
69             except exceptions.MiddlewareNotUsed:
70                 continue
71-
72+            instances[middleware_path] = mw_instance
73             if hasattr(mw_instance, 'process_request'):
74                 self._request_middleware.append(mw_instance.process_request)
75             if hasattr(mw_instance, 'process_view'):
76                 self._view_middleware.append(mw_instance.process_view)
77+               
78+        for middleware_path in outgoing_middleware_order:
79+            if not middleware_path in instances: # If it MiddlewareNotUsed
80+                continue
81+            mw_instance = instances[middleware_path]
82             if hasattr(mw_instance, 'process_response'):
83-                self._response_middleware.insert(0, mw_instance.process_response)
84+                self._response_middleware.append(mw_instance.process_response)
85             if hasattr(mw_instance, 'process_exception'):
86-                self._exception_middleware.insert(0, mw_instance.process_exception)
87+                self._exception_middleware.append(mw_instance.process_exception)
88 
89     def get_response(self, request):
90         "Returns an HttpResponse object for the given HttpRequest"