convert requests.models.Response to Django HttpResponse
Question:
In my Django project, I need to get/post some data to a third-party url in my view, and redirect to the web page it provides. For example, I can simply do something like
class TestView(TemplateView):
def get(self, request, *args, **kwargs):
data = {
'order_id': 88888,
'subject': 'haha',
'rn_check': 'F',
'app_pay': 'T',
}
url = 'http://some-third-party-api-url?order_id=88888&subject=haha&...'
return HttpResponseRedirect(url)
However I want to use this third-party api as a wrapped SDK , like
class TestView(TemplateView):
def get(self, request, *args, **kwargs):
from sucre.alipay_sdk.base import Alipay
from sucre.alipay_sdk import alipay_config
from django.http import HttpResponse
alipay = Alipay(alipay_config)
data = {
'order_id': 88888,
'subject': 'haha',
'rn_check': 'F',
'app_pay': 'T',
}
'''alipay api is wrapped in a sdk'''
'''and return a requests.models.Response instance'''
result = alipay.api('pay', data)
return HttpResponse(result)
and the api code:
def api(self, service, data):
''' some logics here '''
import requests
response = requests.get(url, data=data)
return response
But seems HttpResponse(result) is not the correct way to convert a requests.models.Response instance to HttpResponse… The layout is bad, and some more encoding issues, etc…Is there a correct way to convert requests response to Django HttpResponse?
Updates:
HttpResponse(result) worked, but some css of the page was lost. This might be related with using requests.
Answers:
This may help you :
requests.models.Response
class which,has json() method (according to the documentation) that deserializes the JSON response into a Python object using json.loads(). Try to print following and you can access whatever you are looking for.
print yourResponse.json()
This should works:
from django.http import HttpResponse
import requests
requests_response = requests.get('/some-url/')
django_response = HttpResponse(
content=requests_response.content,
status=requests_response.status_code,
content_type=requests_response.headers['Content-Type']
)
return django_response
To add to paivatulio’s answer, you can forward the headers like so:
for k, v in requests_response.headers.items():
django_response[k] = v
To add to Brian Loughnane’s answer: when I tried the solution:
for k, v in requests_response.headers.items():
django_response[k] = v
I got an error from django: AssertionError: Hop-by-hop headers not allowed
I don’t know if it’s the best solution but I "fixed" it by removing the offending headers.
from wsgiref.util import is_hop_by_hop
for k, v in requests_response.headers.items():
if not is_hop_by_hop(k):
django_response[k] = v
I don’t know if this should be a comment but I don’t have enough reputation to post comments, but this might help:
If you came searching for Django Rest Framework way of doing this, we can modify @paivatulio’s answer like this:
import requests
from rest_framework.response import Response
requests_response = requests.get('/some-url/')
def covert_to_drf_response(response):
drf_response = Response(
data=requests_response.json(),
status=requests_response.status_code),
)
return drf_response
drf_response = convert_to_drf_response(requests_response)
This might also be helpful if you prefer to use DRF’s Response over HttpResponse for the reasons stated here
You can also set your content_type as @paivatulio did.
In my Django project, I need to get/post some data to a third-party url in my view, and redirect to the web page it provides. For example, I can simply do something like
class TestView(TemplateView):
def get(self, request, *args, **kwargs):
data = {
'order_id': 88888,
'subject': 'haha',
'rn_check': 'F',
'app_pay': 'T',
}
url = 'http://some-third-party-api-url?order_id=88888&subject=haha&...'
return HttpResponseRedirect(url)
However I want to use this third-party api as a wrapped SDK , like
class TestView(TemplateView):
def get(self, request, *args, **kwargs):
from sucre.alipay_sdk.base import Alipay
from sucre.alipay_sdk import alipay_config
from django.http import HttpResponse
alipay = Alipay(alipay_config)
data = {
'order_id': 88888,
'subject': 'haha',
'rn_check': 'F',
'app_pay': 'T',
}
'''alipay api is wrapped in a sdk'''
'''and return a requests.models.Response instance'''
result = alipay.api('pay', data)
return HttpResponse(result)
and the api code:
def api(self, service, data):
''' some logics here '''
import requests
response = requests.get(url, data=data)
return response
But seems HttpResponse(result) is not the correct way to convert a requests.models.Response instance to HttpResponse… The layout is bad, and some more encoding issues, etc…Is there a correct way to convert requests response to Django HttpResponse?
Updates:
HttpResponse(result) worked, but some css of the page was lost. This might be related with using requests.
This may help you :
requests.models.Response
class which,has json() method (according to the documentation) that deserializes the JSON response into a Python object using json.loads(). Try to print following and you can access whatever you are looking for.
print yourResponse.json()
This should works:
from django.http import HttpResponse
import requests
requests_response = requests.get('/some-url/')
django_response = HttpResponse(
content=requests_response.content,
status=requests_response.status_code,
content_type=requests_response.headers['Content-Type']
)
return django_response
To add to paivatulio’s answer, you can forward the headers like so:
for k, v in requests_response.headers.items():
django_response[k] = v
To add to Brian Loughnane’s answer: when I tried the solution:
for k, v in requests_response.headers.items():
django_response[k] = v
I got an error from django: AssertionError: Hop-by-hop headers not allowed
I don’t know if it’s the best solution but I "fixed" it by removing the offending headers.
from wsgiref.util import is_hop_by_hop
for k, v in requests_response.headers.items():
if not is_hop_by_hop(k):
django_response[k] = v
I don’t know if this should be a comment but I don’t have enough reputation to post comments, but this might help:
If you came searching for Django Rest Framework way of doing this, we can modify @paivatulio’s answer like this:
import requests
from rest_framework.response import Response
requests_response = requests.get('/some-url/')
def covert_to_drf_response(response):
drf_response = Response(
data=requests_response.json(),
status=requests_response.status_code),
)
return drf_response
drf_response = convert_to_drf_response(requests_response)
This might also be helpful if you prefer to use DRF’s Response over HttpResponse for the reasons stated here
You can also set your content_type as @paivatulio did.