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 within the middleware, but is then the correct user within the views. I've left the default authentication and session middleware django uses within the settings.
There is a similar question here: Django, request.user is always Anonymous User But doesn't overly answer the total question because I'm not using different authentication methods, and djangos authentication is running before I invoke my own middleware.
Is there a way, while using DRF, to get the request.user within the middleware? I'll show some sample code here:
class SampleMiddleware(object):
def process_view(self, request, view_func, view_args, view_kwargs):
#This will be AnonymousUser. I need it to be the actual user making the request.
print (request.user)
def process_response(self, request, response):
return response
with process_request:
class SampleMiddleware(object):
def process_request(self, request):
#This will be AnonymousUser. I need it to be the actual user making the request.
print (request.user)
def process_response(self, request, response):
return response
Based on Daniel Dubovski's very elegant solution above, here's an example of middleware for Django 1.11:
Daniel Dubovski's solution is probably the best in most cases.
The problem with the lazy object approach is if you need to rely on the side effects. In my case, I need something to happen for each request, no matter what.
If I'd use a special value like
request.custom_prop
, it has to be evaluated for each request for the side effects to happen. I noticed that other people are settingrequest.user
, but it doesn't work for me since some middleware or authentication class overwrites this property.What if DRF supported its own middleware? Where could I plug it in? The easiest way in my case (I don't need to access the
request
object, only the authenticated user) seems to be to hook into the authentication class itself:Then I could just replace this line in my settings:
I'm not promoting this solution, but maybe it will help someone else.
Pros:
Cons:
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 :
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
Hey guys I've solved this problem by getting DRF token from the requests and loading request.user to the user associated to that model.
I had the default django authentication and session middleware, but it seems DRF was using it's token auth after middleware to resolve the user (All requests were CORS requests, this might have been why). Here's my updated middleware class:
This can be used on process_view or process_request as well.
Hopefully this can help someone out in the future.
I wasn't quite happy with the solutions out there. Here's a solution that uses some DRF internals to make sure that the correct authentication is applied in the middleware, even if the view has specific permissions classes. It uses the middleware hook
process_view
which gives us access to the view we're about to hit:Note that this doesn't avoid having to authenticate twice. DRF will still happily authenticate right afterwards.
I know it's not exactly answering the 'can we access that from the middleware' question, but I think it's a more elegant solution VS doing the same work in the middleware VS what DRJ does in its base view class. At least for what I needed, it made more sense to add here.
Basically, I'm just overriding the method 'perform_authentication()' from DRF's code, since I needed to add more things related to the current user in the request. The method just originally call 'request.user'.
After that in your own views, instead of settings APIView from DRF as a parent class, simply set that class as a parent.