Django Access URL Arguments Through Middleware
Oct 02, 2019 · 2 Min Read · 6 Likes · 4 CommentsLets say you have an API which is being used by many stores. Now for a specific store ABC, they want to have a different response format. So how would you make this implementation generic without making different views for store ABC? Simple, use middleware.
How it works
First update the url like this:
url = [
path('api/v1/<str:store_code>/', include("api.urls")),
]
Then write a middleware to capture the value of store_code
:
class StoreCodeMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
response = self.get_response(request)
return response
def process_view(request, view_func, view_args, view_kwargs):
store_code = view_kwargs.get('store_code', None)
if store_code:
request.session['store_code'] = store_code
Here I am using process_view
to capture the url argument. Because in process_view
, there is a keyword argument named view_kwargs
which is a dictionary, which will be passed to the view. Now, we can attach the store_code
to request
object through another middleware.
class StoreToRequestMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
store_code = request.session.get('store_code', None)
if store_code:
request.store, _ = Store.objects.get_or_create(code=store_code) # assuming `Store` is the model class where store information are being stored
response = self.get_response(request)
return response
Now lets add these middlewares in settings.py
:
MIDDLEWARES = [
# rest of the middlewares
'path.to.StoreCodeMiddleware',
'path.to.StoreToRequestMiddleware'
]
Make sure StoreCodeMiddleware
is on top of StoreToMiddleware
.
Usage
Lets say you have an API view, then use store
info like this:
class StoreAPI(APIView):
def get(self, request, *args, **kwargs):
serializer = CommonSerializer(request.store)
if request.store.code == "ABC":
serializer = ABCSerializer(request.store)
return Response(serializer.data)
Another usage scenario
Lets say you are using a package like black box which provides everything through url(means you can’t override anything inside the views or models), then the approach is useful. For example, when using djoser
or django-rest-auth
, they provide authentication services(like login, registration, password reset etc), you just need to include their url in your root url. When using these libraries, you might need to store additional information coming through url; then the given approach is really helpful.
Hope it helps. Thanks for reading. Cheers!!
Last updated: Jul 13, 2024
I won't spam you. Unsubscribe at any time.