Don't call the view yourself (and return a result) from process_view

calling the view yourself short-circuits the correct handling, which is not
what we want. It's not abundantly clear from the docs that this is generally
not what we want, but it is cimplied:

> It should return either None or an HttpResponse object. If it returns None,
> Django will continue processing this request, executing any other
> process_view() middleware and, then, the appropriate view. If it returns an
> HttpResponse object, Django won’t bother calling the appropriate view; it’ll
> apply response middleware to that HttpResponse and return the result.

We don't want to do any short-circuiting here, we just want to measure time
and have a view_name to display. Moving stuff around fixes it.

(That this was an error became clear when I wanted to do process_exception
in another Middleware, and that was never called)
This commit is contained in:
Klaas van Schelven
2024-05-24 13:48:24 +02:00
parent 049053cc51
commit c811ddb6fb

View File

@@ -33,22 +33,19 @@ class PerformanceStatsMiddleware:
"""TSTTCPW to get some handle on view-performance (mostly for UI views). The direct cause for introducing this is
that I got sent on a wild goose chase by the Django Debug Toolbar, which reported long (>100ms) CPU times for some
view when it was the DJDT itself that was causing most of that time.
Yes this only measures the time spent in the view function itself and not the time in the surrounding Middleware,
but the whole point is to measure where individual views might be slow.
"""
def __init__(self, get_response):
self.get_response = get_response
self.view_name = "<<unknown>>"
def __call__(self, request):
return self.get_response(request)
t0 = time()
result = self.get_response(request)
took = (time() - t0) * 1000
performance_logger.info(f"{took:6.2f}ms / {len(connection.queries)} queries: '{ self.view_name }'")
return result
def process_view(self, request, view_func, view_args, view_kwargs):
t0 = time()
result = view_func(request, *view_args, **view_kwargs)
took = (time() - t0) * 1000
if not request.path.startswith("/static"):
performance_logger.info(f"{took:6.2f}ms / {len(connection.queries)} queries: '{ view_func.__name__ }'")
return result
self.view_name = view_func.__name__
return None