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 django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
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.

Reply via email to