Opened 8 years ago
Last modified 5 weeks ago
#26626 new New feature
Update decorator_from_middleware to work with new-style middleware
Reported by: | Tim Graham | Owned by: | |
---|---|---|---|
Component: | HTTP handling | Version: | dev |
Severity: | Normal | Keywords: | |
Cc: | Adam Johnson | Triage Stage: | Accepted |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
@carljm is working on it: "I did work on updating decorator_from_middleware
yesterday and have an in-progress patch. I don't think we should plan on the patch for alpha (it's nontrivial and will need review), but if it's ok to do it as a follow-up cleanup fix for beta, then yeah I think it's be good to have it for 1.10.
Change History (7)
comment:1 by , 8 years ago
Owner: | changed from | to
---|---|
Status: | new → assigned |
comment:2 by , 8 years ago
comment:3 by , 8 years ago
A use case for this is tests. I have a middleware that handles temporary unavailability by showing a loading page/returning HTTP 503 for certain exceptions.
This particular middleware uses custom logic in __call__
and process_exception
. decorator_from_middleware
makes it easy to test this middleware:
@override_settings(MAINTENANCE_MODE=True) def test_maintenance_mode(self): @decorator_from_middleware(TemporaryUnavailable) def view(): raise AssertionError("don't call") response = view(RequestFactory().get('/') assert response.status_code == 503
Of course, I could craft my own get_response, initiate the middleware and call __call__
or process_exception
directly but that is ugly and easy to get some details wrong, especially when the test involves exceptions.
follow-up: 5 comment:4 by , 8 years ago
Another use case:
We have a custom authentication mechanism that is not tied to contrib.admin for our main site.
However, we use contrib.auth for administrative accounts. To make it very clear which views needs a real user, we have disabled the auth middleware globally and use a custom admin site that selectively enables auth:
from django.contrib import admin from django.contrib.auth.middleware import AuthenticationMiddleware from django.utils.decorators import decorator_from_middleware auth_decorator = decorator_from_middleware(AuthenticationMiddleware) class AdminSite(admin.AdminSite): def admin_view(self, view, cacheable=False): super_wrapper = super().admin_view(view, cacheable=cacheable) return auth_decorator(super_wrapper)
(This use case is fine and works fine in Django 1.10 since Django's built in AuthenticationMiddleware
is both old and new-style, but I just wanted to highlight that decorator_from_middleware
is useful in different contexts)
comment:5 by , 7 years ago
The following function takes a new-style middleware class and makes a view decorator out of it. It's used in code that me and @pelme are working on, though not as a decorator.
def decorator_from_middleware_new(new_middleware_cls): def view_decorator(view_function): def view(request, *args, **kwargs): def get_response(request_inner): assert request is request_inner try: return view_function(request, *args, **kwargs) except Exception as e: new_middleware.process_exception(request, e) return HttpResponseServerError() new_middleware = new_middleware_cls(get_response) return new_middleware(request) return view return view_decorator
comment:6 by , 3 years ago
Owner: | removed |
---|---|
Status: | assigned → new |
comment:7 by , 5 weeks ago
Cc: | added |
---|
Absent a compelling use case for this update and due to some limitations in how effectively
decorator_from_middleware
can make the transformation, we decided not to move forward with this. A query about it has been raised on Reddit. I've asked if that poster can give a use case here.