将requests.models.Response转换为Django HttpResponse

14
在我的Django项目中,我需要在视图中向第三方URL获取/提交一些数据,并重定向到它提供的网页。例如,我可以简单地执行以下操作:
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)

然而,我希望将这个第三方API作为一个封装好的SDK来使用,就像:

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)

以及 API 代码:

def api(self, service, data):
    ''' some logics here '''
    import requests
    response = requests.get(url, data=data)
    return response

但是似乎HttpResponse(result)不是将requests.models.Response实例转换为HttpResponse的正确方法...布局不好,还有一些编码问题等等...是否有正确的方法将requests响应转换为Django HttpResponse?


更新:

HttpResponse(result)起作用了,但页面的某些CSS丢失了。这可能与使用requests有关。


请查看mcve - Olian04
感谢@Olian04的建议。(因为这是我第一次使用stackoverflow提问)然而,完成的代码太长了,而且与问题本身——将requests的响应转换为HttpResponse无关。 - Ella SUN
5个回答

29

这应该可以工作:

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

对我有用。谢谢! - Darth Kangooroo

1

补充 Brian Loughnane 的回答:当我尝试了这个解决方案:

for k, v in requests_response.headers.items():
    django_response[k] = v

我从Django中收到了一个错误信息: AssertionError: Hop-by-hop headers not allowed(禁止跳跃式头部)。我不确定这是否是最佳解决方案,但我通过删除有问题的头部来“修复”它。
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

0

我不确定这是否应该是一条评论,但我没有足够的声望来发布评论,但这可能会有所帮助:

如果您正在寻找Django Rest Framework的解决方法,我们可以像这样修改@paivatulio的答案:

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)

如果您因为这里所述的原因更喜欢使用DRF的响应而不是HttpResponse,那么这也可能会有所帮助。

您还可以像@paivatulio一样设置您的content_type。


0
这可能会对你有所帮助: < p > < code > requests.models.Response 类,它具有json()方法(根据文档),该方法使用json.loads()将JSON响应反序列化为Python对象。尝试打印以下内容,您可以访问您正在寻找的任何内容。 < / p>
print yourResponse.json()

0
补充paivatulio的回答,您可以这样转发头部:
for k, v in requests_response.headers.items():
  django_response[k] = v

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接