Last active
June 27, 2023 17:01
-
-
Save LucasRoesler/700d281d528ecb7895c0 to your computer and use it in GitHub Desktop.
A Django middleware that process JSON data into the appropriate GET or POST variable. I use this with AngularJS, by default POST requests are sent as JSON instead of the urlencoded data expected by Django.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class JSONMiddleware(object): | |
""" | |
Process application/json requests data from GET and POST requests. | |
""" | |
def process_request(self, request): | |
if 'application/json' in request.META['CONTENT_TYPE']: | |
# load the json data | |
data = json.loads(request.body) | |
# for consistency sake, we want to return | |
# a Django QueryDict and not a plain Dict. | |
# The primary difference is that the QueryDict stores | |
# every value in a list and is, by default, immutable. | |
# The primary issue is making sure that list values are | |
# properly inserted into the QueryDict. If we simply | |
# do a q_data.update(data), any list values will be wrapped | |
# in another list. By iterating through the list and updating | |
# for each value, we get the expected result of a single list. | |
q_data = QueryDict('', mutable=True) | |
for key, value in data.iteritems(): | |
if isinstance(value, list): | |
# need to iterate through the list and upate | |
# so that the list does not get wrapped in an | |
# additional list. | |
for x in value: | |
q_data.update({key: x}) | |
else: | |
q_data.update({key: value}) | |
if request.method == 'GET': | |
request.GET = q_data | |
if request.method == 'POST': | |
request.POST = q_data | |
return None |
Thank you for the gist i was previously using a transform request in my angular scripts but this is better
Yes like dusan87 mentioned django throws an error in case no 'CONTENT_TYPE' key is present in the request.
You can use a try and except as suggested or just add request.META.get('CONTENT_TYPE') to the if condition.
For example a statement like,
if request.META.get('CONTENT_TYPE') and 'application/json' in request.META.get('CONTENT_TYPE'):
...
For completeness' sake, import json and QueryDict
from django.http import HttpResponse, QueryDict
import json
class JSONMiddleware:
"""
Process application/json requests data from GET and POST requests.
"""
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
if request.META.get('CONTENT_TYPE') and 'application/json' in request.META.get('CONTENT_TYPE'):
try:
data = json.loads(request.body)
q_data = QueryDict('', mutable=True)
for key, value in data.items():
if isinstance(value, list):
for x in value:
q_data.update({key: x})
else:
q_data.update({key: value})
if request.method == 'GET':
request.GET = q_data
if request.method == 'POST':
request.POST = q_data
return self.get_response(request)
except json.JSONDecodeError:
return HttpResponse("JSON Decode Error", status=400)
return self.get_response(request)
Updated to Django 2.2 and Python 3 and applied all comments suggestions. Also return a "Bad Request" in case of JSON parsing problem.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
There is a KeyError exception in case there is no content_type key/value pair in request. I'd recommend you just to put try except block to catch this error and return None as well