Hi there,
After refactoring the middlewares to new-style middlewares as we have them now,
I am left with two pain points:
* atomic requests are still special cased and not in a middleware
* process_view is as useless as always (it can neither alter nor convert
args/kwargs or the view)
To change this I am proposing the following changes:
* Deprecate request.urlconf and provide a way to set the urlconf __before__
the middleware chain is entered
* Resolve view before the middleware chain is entered
This will imo improve existing code and allow for many new possibilities:
1.) Replace or transform kwargs/view. If the view is resolved before the
middleware chain is entered, we can set resolver_match immediatelly effectively
making process_view useless:
class MyMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
view, args, kwargs = request.resolver_match
# If you call view() directly here you can return a response and do
what process_view could do:
return view(request, args, kwargs)
# ... or you could add a profiling decorator to the view without
affecting the rest of the middlewares
# process_view did not allow for this feature in the past (you couldn't
alter the view, just call and return a response):
request.resolver_match.func = profiler(request.resolver_match.func)
return self.get_response(request)
2.) Rewrite atomic requests to a middleware again:
class TransactionMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
# Either as it is now by simply covering the view
request.resolver_match.func =
make_view_atomic(request.resolver_match.func)
# ... or by actually covering the following middleware layers too:
# This was not possible before because middlewares wouldn't have access
to the view
# Excemption would still be controlled by the view itself
view, args, kwargs = request.resolver_match
get_response = self.get_response
non_atomic_requests = getattr(view, '_non_atomic_requests', set())
for db in connections.all():
if db.settings_dict['ATOMIC_REQUESTS'] and db.alias not in
non_atomic_requests:
get_response = transaction.atomic(using=db.alias)(view)
return get_response(request)
The only thing left is to provide a way to dynamically alter the URL conf;
which we can do by adding a setting (yes a setting) which points to a callable
with a default implementation of:
def urlconf_factory(request):
return settings.ROOT_URLCONF
Before entering the middleware chain we'd then do
urlconf = urlconf_factory(request)
set_urlconf(urlconf)
resolver = get_resolver(urlconf)
request.resolver_match = resolver.resolve(request.path_info)
request.urlconf = urlconf # if needed
-- this would have the added benefit of allowing proper reversal of urls
inside middlewares if needed (the correct urlconf is already set in the thread
local)
What do you think?
Cheers,
Florian
--
You received this message because you are subscribed to the Google Groups
"Django developers (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/django-developers.
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-developers/a4d843d8-adce-4c61-aa52-c722c5d94f39%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.