31 | | for middleware_path in settings.MIDDLEWARE_CLASSES: |
32 | | try: |
33 | | dot = middleware_path.rindex('.') |
34 | | except ValueError: |
35 | | raise exceptions.ImproperlyConfigured, '%s isn\'t a middleware module' % middleware_path |
36 | | mw_module, mw_classname = middleware_path[:dot], middleware_path[dot+1:] |
37 | | try: |
38 | | mod = __import__(mw_module, {}, {}, ['']) |
39 | | except ImportError, e: |
40 | | raise exceptions.ImproperlyConfigured, 'Error importing middleware %s: "%s"' % (mw_module, e) |
41 | | try: |
42 | | mw_class = getattr(mod, mw_classname) |
43 | | except AttributeError: |
44 | | raise exceptions.ImproperlyConfigured, 'Middleware module "%s" does not define a "%s" class' % (mw_module, mw_classname) |
45 | | |
46 | | try: |
47 | | mw_instance = mw_class() |
48 | | except exceptions.MiddlewareNotUsed: |
49 | | continue |
50 | | |
| 25 | mw_instances = [ _middleware_instance_from_path(mw_path) for mw_path |
| 26 | in mw_paths ] |
| 27 | for mw_instance in mw_instances: |
| 37 | def _load_middleware_from_dict(self, mw_dict): |
| 38 | # fill the instances dict so that we have only one instance of each |
| 39 | # middleware |
| 40 | mw_instances = _middleware_instances_from_dict(mw_dict) |
| 41 | # it would be easy to do validation here, but it would be expensive |
| 42 | # for mw_path, mw_inst in mw_instances.items(): |
| 43 | # for attr in ('request', 'view', 'response', 'exception'): |
| 44 | # if hasattr(mw_inst, attr) and mw_path not in mw_dict[attr]: |
| 45 | # raise ImproperlyConfigured("") |
| 46 | |
| 47 | self._request_middleware = _particular_middleware_from_dicts('request', |
| 48 | mw_instances, mw_dict) |
| 49 | self._view_middleware = _particular_middleware_from_dicts('view', |
| 50 | mw_instances, mw_dict) |
| 51 | self._response_middleware = _particular_middleware_from_dicts('response', |
| 52 | mw_instances, mw_dict) |
| 53 | self._exception_middleware = _particular_middleware_from_dicts('exception', |
| 54 | mw_instances, mw_dict) |
| 55 | |
| 56 | def load_middleware(self): |
| 57 | """ |
| 58 | Populate middleware lists from settings.MIDDLEWARE_CLASSES. |
| 59 | |
| 60 | Must be called after the environment is fixed (see __call__). |
| 61 | """ |
| 62 | from django.conf import settings |
| 63 | if isinstance(settings.MIDDLEWARE_CLASSES, (tuple, list)): |
| 64 | self._load_middleware_from_list(settings.MIDDLEWARE_CLASSES) |
| 65 | elif isinstance(settings.MIDDLEWARE_CLASSES, (dict)): |
| 66 | self._load_middleware_from_dict(settings.MIDDLEWARE_CLASSES) |
| 67 | else: |
| 68 | raise exceptions.ImproperlyConfigured("MIDDLEWARE_CLASSES setting " |
| 69 | "has to be either a tuple, list or a dict.") |
| 70 | |
| 185 | def validate_middleware(self): |
| 186 | # A very rough attempt at validation, doesn't load the middleware. |
| 187 | # Note that this assumes that if middleware has a process_foo method, |
| 188 | # then it has to be registered in MIDDLEWARE_CLASSES['foo']. |
| 189 | from django.conf import settings |
| 190 | # if MIDDLEWARE_CLASSES is a list, no easy way to validate |
| 191 | if isinstance(settings.MIDDLEWARE_CLASSES, (dict)): |
| 192 | mw_dict = settings.MIDDLEWARE_CLASSES |
| 193 | mw_instances = _middleware_instances_from_dict(mw_dict) |
| 194 | for mw_path, mw_inst in mw_instances.items(): |
| 195 | for attr in ('request', 'view', 'response', 'exception'): |
| 196 | if hasattr(mw_inst, attr) and mw_path not in mw_dict[attr]: |
| 197 | raise exceptions.ImproperlyConfigured("%s has to " |
| 198 | "be enabled for %s processing in " |
| 199 | "MIDDLEWARE_CLASSES setting." % (mw_path, attr)) |
| 200 | |
| 225 | def _middleware_instance_from_path(middleware_path): |
| 226 | try: |
| 227 | dot = middleware_path.rindex('.') |
| 228 | except ValueError: |
| 229 | raise exceptions.ImproperlyConfigured, '%s isn\'t a middleware module' % middleware_path |
| 230 | mw_module, mw_classname = middleware_path[:dot], middleware_path[dot+1:] |
| 231 | try: |
| 232 | mod = __import__(mw_module, {}, {}, ['']) |
| 233 | except ImportError, e: |
| 234 | raise exceptions.ImproperlyConfigured, 'Error importing middleware %s: "%s"' % (mw_module, e) |
| 235 | try: |
| 236 | mw_class = getattr(mod, mw_classname) |
| 237 | except AttributeError: |
| 238 | raise exceptions.ImproperlyConfigured, 'Middleware module "%s" does not define a "%s" class' % (mw_module, mw_classname) |
| 239 | # I'm ignoring the MiddlewareNotUsed exception as it's not used in Django |
| 240 | # according to grep, not documented and the only use case I can see is to |
| 241 | # raise it in custom middleware __init__ to disable the middleware |
| 242 | # temporarily. That can be better achieved with disabling it in settings |
| 243 | # (where it is explicit and visible). If everybody is happy with that, the |
| 244 | # exception should be removed from core.exceptions. See also #7820. |
| 245 | return mw_class() |
| 246 | |
| 247 | def _particular_middleware_from_dicts(mw_type, mw_instance_dict, mw_dict): |
| 248 | mw_instance_list = [] |
| 249 | for mw_path in mw_dict.get(mw_type, []): |
| 250 | mw_instance = mw_instance_dict[mw_path] |
| 251 | if not hasattr(mw_instance, 'process_' + mw_type): |
| 252 | raise exceptions.ImproperlyConfigured("%s middleware needs " |
| 253 | "a 'process_%s' method, but it's missing from %s." |
| 254 | % (mw_type.title(), mw_type, mw_path)) |
| 255 | mw_instance_list.append(mw_instance) |
| 256 | return mw_instance_list |
| 257 | |
| 258 | def _middleware_instances_from_dict(mw_dict): |
| 259 | mw_instances = {} |
| 260 | for mw_path_tuple in mw_dict.values(): |
| 261 | for mw_path in mw_path_tuple: |
| 262 | if mw_path not in mw_instances: |
| 263 | mw_instances[mw_path] = _middleware_instance_from_path(mw_path) |
| 264 | return mw_instances |