Middleware no global en Django

En Django hay un archivo de configuración que define el middleware que se ejecutará en cada solicitud. Esta configuración de middleware es global. ¿Hay alguna manera de especificar un conjunto de middleware por vista? Quiero que las URL específicas utilicen un conjunto de middleware diferente del conjunto global.

Quieres decorator_from_middleware .

 from django.utils.decorators import decorator_from_middleware @decorator_from_middleware(MyMiddleware) def view_function(request): #blah blah 

No se aplica a las URL, pero funciona por vista, por lo que puede tener un control preciso sobre su efecto.

Tengo una solución real para este problema. Advertencia; Es un poco de un hack.

 """ Allows short-curcuiting of ALL remaining middleware by attaching the @shortcircuitmiddleware decorator as the TOP LEVEL decorator of a view. Example settings.py: MIDDLEWARE_CLASSES = ( 'django.middleware.common.CommonMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', # THIS MIDDLEWARE 'myapp.middleware.shortcircuit.ShortCircuitMiddleware', # SOME OTHER MIDDLE WARE YOU WANT TO SKIP SOMETIMES 'myapp.middleware.package.MostOfTheTimeMiddleware', # MORE MIDDLEWARE YOU WANT TO SKIP SOMETIMES HERE ) Example view to exclude from MostOfTheTimeMiddleware (and any subsequent): @shortcircuitmiddleware def myview(request): ... """ def shortcircuitmiddleware(f): """ view decorator, the sole purpose to is 'rename' the function '_shortcircuitmiddleware' """ def _shortcircuitmiddleware(*args, **kwargs): return f(*args, **kwargs) return _shortcircuitmiddleware class ShortCircuitMiddleware(object): """ Middleware; looks for a view function named '_shortcircuitmiddleware' and short-circuits. Relies on the fact that if you return an HttpResponse from a view, it will short-circuit other middleware, see: https://docs.djangoproject.com/en/dev/topics/http/middleware/#process-request """ def process_view(self, request, view_func, view_args, view_kwargs): if view_func.func_name == "_shortcircuitmiddleware": return view_func(request, *view_args, **view_kwargs) return None 

Editar: eliminó la versión anterior que ejecutaba la vista dos veces.

Aquí hay una solución que usé recientemente para abordar el escenario que presentó en un comentario a la respuesta de Ned …

Se supone que:

A) este es un middleware personalizado o uno que puede ampliar / envolver con su propia clase de middleware

B) su lógica puede esperar hasta process_view lugar de process_request , porque en process_view puede inspeccionar el parámetro view_func después de que se haya resuelto. (O puede ajustar el código a continuación para usar los urlresolvers como lo indica Ignacio).

 # settings.py EXCLUDE_FROM_MY_MIDDLEWARE = set('myapp.views.view_to_exclude', 'myapp.views.another_view_to_exclude') # some_middleware.py from django.conf import settings def process_view(self, request, view_func, view_args, view_kwargs): # Get the view name as a string view_name = '.'.join((view_func.__module__, view_func.__name__)) # If the view name is in our exclusion list, exit early exclusion_set = getattr(settings, 'EXCLUDE_FROM_MY_MIDDLEWARE', set()) if view_name in exclusion_set: return None # ... middleware as normal ... # # Here you can also set a flag of some sort on the `request` object # if you need to conditionally handle `process_response` as well. 

Puede haber una manera de generalizar aún más este patrón, pero esto logró mi objective bastante bien.

Para responder tu pregunta más general, no creo que haya nada en las bibliotecas de Django que te ayude con esto actualmente. Sería un buen tema para la lista de correo de django-users si aún no se haya abordado allí.

Puede usar el método process_view, que se llama antes de llamar a la función de vista. En process_view puede verificar, si esta vista requiere esta intercepción de middleware.

Use django.core.urlresolvers.resolve() contra request.path en un contenedor para que el middleware intente ver si la vista está dentro de la aplicación, y omita el procesamiento si es así.

Lo mejor que he podido encontrar es usar if request.path_info.startswith (‘…’) para omitir el middleware simplemente devolviendo la solicitud. Ahora, puede crear middleware solo por el hecho de saltar y luego heredarlo. Tal vez podría hacer algo aún más sencillo y guardar esa lista en su configuración.py y luego omitir todo eso. Si estoy equivocado de alguna manera, hágamelo saber.

Django urlmiddleware permite aplicar middleware solo a vistas que están asignadas a direcciones URL específicas.

Creo que esta es la manera fácil de excluir una vista de middleware

  from django.core.urlresolvers import resolve current_url = resolve(request.path_info).url_name if want to exclude url A, class your_middleware: def process_request(request): if not current_url == 'A': "here add your code"