Django and Middleware which uses request.user is always Anonymous

前端 未结 7 1206
天命终不由人
天命终不由人 2021-01-30 10:37

I\'m trying to make middleware which alters some fields for the user based on subdomain, etc...

The only problem is the request.user always comes in as AnonymousUser wit

7条回答
  •  星月不相逢
    2021-01-30 11:21

    Came across this today while having the same problem.

    TL;DR;

    Skip below for code example


    Explanation

    Thing is DRF have their own flow of things, right in the middle of the django request life-cycle.

    So if the normal middleware flow is :

    1. request_middleware (before starting to work on the request)
    2. view_middleware (before calling the view)
    3. template_middleware (before render)
    4. response_middleware (before final response)

    DRF code, overrides the default django view code, and executes their own code.

    In the above link, you can see that they wrap the original request with their own methods, where one of those methods is DRF authentication.

    So back to your question, this is the reason using request.user in a middleware is premature, as it only gets it's value after view_middleware** executes.

    The solution I went with, is having my middleware set a LazyObject. This helps, because my code (the actual DRF ApiVIew) executes when the actual user is already set by DRF's authentication. This solution was proposed here together with a discussion.

    Might have been better if DRF had a better way to extend their functionality, but as things are, this seems better than the provided solution (both performance and readability wise).


    Code Example

    from django.utils.functional import SimpleLazyObject
    
    def get_actual_value(request):
        if request.user is None:
            return None
    
        return request.user #here should have value, so any code using request.user will work
    
    
    class MyCustomMiddleware(object):
        def process_request(self, request):
            request.custom_prop = SimpleLazyObject(lambda: get_actual_value(request))
    

提交回复
热议问题