Ticket #730: middleware_ordering_with_path-weight_tuples-backwards-compatible.diff

File middleware_ordering_with_path-weight_tuples-backwards-compatible.diff, 4.6 KB (added by mrts, 7 years ago)

Added backwards-compatibility and uniqueness checks. All tests pass as of r8219. See notes below.

  • django/core/handlers/base.py

     
    11import sys
     2try:
     3    set
     4except NameError:
     5    from sets import Set as set
    26
    37from django import http
    48from django.core import signals
     
    2933        self._view_middleware = []
    3034        self._response_middleware = []
    3135        self._exception_middleware = []
    32         for middleware_path in settings.MIDDLEWARE_CLASSES:
    33             try:
    34                 dot = middleware_path.rindex('.')
    35             except ValueError:
    36                 raise exceptions.ImproperlyConfigured, '%s isn\'t a middleware module' % middleware_path
    37             mw_module, mw_classname = middleware_path[:dot], middleware_path[dot+1:]
    38             try:
    39                 mod = __import__(mw_module, {}, {}, [''])
    40             except ImportError, e:
    41                 raise exceptions.ImproperlyConfigured, 'Error importing middleware %s: "%s"' % (mw_module, e)
    42             try:
    43                 mw_class = getattr(mod, mw_classname)
    44             except AttributeError:
    45                 raise exceptions.ImproperlyConfigured, 'Middleware module "%s" does not define a "%s" class' % (mw_module, mw_classname)
    4636
    47             try:
    48                 mw_instance = mw_class()
    49             except exceptions.MiddlewareNotUsed:
    50                 continue
     37        if not settings.MIDDLEWARE_CLASSES:
     38            return
    5139
     40        # (middleware_path, weight) tuples in MIDDLEWARE_CLASSES,
     41        # heavier items processed first in outbound methods
     42        # OR just backwards-compatible strings
     43        middleware_list = None
     44        if isinstance(settings.MIDDLEWARE_CLASSES[0], tuple):
     45            # uniqueness test
     46            key_set = list(set([mw[1] for mw in settings.MIDDLEWARE_CLASSES]))
     47            if len(key_set) != len(settings.MIDDLEWARE_CLASSES):
     48                raise ImproperlyConfigured("Middleware outbound ordering "
     49                        "values have to be unique.")
     50
     51            middleware_list = _middleware_list_from_iterable([(mw[1], mw[0])
     52                for mw in settings.MIDDLEWARE_CLASSES])
     53        else:
     54            middleware_list = _middleware_list_from_iterable(enumerate(
     55                settings.MIDDLEWARE_CLASSES))
     56
     57        if not middleware_list:
     58            return
     59
     60        # inbound
     61        for _, mw_instance in middleware_list:
    5262            if hasattr(mw_instance, 'process_request'):
    5363                self._request_middleware.append(mw_instance.process_request)
    5464            if hasattr(mw_instance, 'process_view'):
    5565                self._view_middleware.append(mw_instance.process_view)
     66
     67        # outbound
     68        middleware_list.sort()
     69        middleware_list.reverse()
     70        for _, mw_instance in middleware_list:
    5671            if hasattr(mw_instance, 'process_response'):
    57                 self._response_middleware.insert(0, mw_instance.process_response)
     72                self._response_middleware.append(mw_instance.process_response)
    5873            if hasattr(mw_instance, 'process_exception'):
    59                 self._exception_middleware.insert(0, mw_instance.process_exception)
     74                self._exception_middleware.append(mw_instance.process_exception)
    6075
    6176    def get_response(self, request):
    6277        "Returns an HttpResponse object for the given HttpRequest"
     
    196211        return force_unicode(script_url[:-len(environ.get('PATH_INFO', ''))])
    197212    return force_unicode(environ.get('SCRIPT_NAME', u''))
    198213
     214def _middleware_list_from_iterable(middleware_iterable):
     215    middleware_list = []
     216    for middleware_tuple in middleware_iterable:
     217        middleware_path = middleware_tuple[1]
     218        try:
     219            dot = middleware_path.rindex('.')
     220        except ValueError:
     221            raise exceptions.ImproperlyConfigured, '%s isn\'t a middleware module' % middleware_path
     222        mw_module, mw_classname = middleware_path[:dot], middleware_path[dot+1:]
     223        try:
     224            mod = __import__(mw_module, {}, {}, [''])
     225        except ImportError, e:
     226            raise exceptions.ImproperlyConfigured, 'Error importing middleware %s: "%s"' % (mw_module, e)
     227        try:
     228            mw_class = getattr(mod, mw_classname)
     229        except AttributeError:
     230            raise exceptions.ImproperlyConfigured, 'Middleware module "%s" does not define a "%s" class' % (mw_module, mw_classname)
     231
     232        try:
     233            mw_instance = mw_class()
     234        except exceptions.MiddlewareNotUsed:
     235            continue
     236        middleware_list.append((middleware_tuple[0], mw_instance))
     237    return middleware_list
     238
Back to Top