如何在Django视图中正确序列化API响应

2024-10-01 05:06:19 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在使用另一个wrapper API调用Giphy API,它返回一个字典列表。我很难序列化数据以将其返回到AJAX

数据返回为InlineResponse200,有三个properties。 (docu

问题是我的视图无法正确返回JSON:

# Traceback
[2020-06-23 14:58:54,086] log: ERROR - Internal Server Error: /get_gifs/
Traceback (most recent call last):
  File "C:\Users\Jonas\AppData\Local\Programs\Python\Python38-32\lib\site-packages\django\core\handlers\exception.py", line 34, in inner
    response = get_response(request)
  File "C:\Users\Jonas\AppData\Local\Programs\Python\Python38-32\lib\site-packages\django\core\handlers\base.py", line 115, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "C:\Users\Jonas\AppData\Local\Programs\Python\Python38-32\lib\site-packages\django\core\handlers\base.py", line 113, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "C:\Users\Jonas\Desktop\finsphere\finsphere\blog\views.py", line 234, in get_gifs
    return JsonResponse(api_response.data[0])
  File "C:\Users\Jonas\AppData\Local\Programs\Python\Python38-32\lib\site-packages\django\http\response.py", line 554, in __init__
    raise TypeError(
TypeError: In order to allow non-dict objects to be serialized set the safe parameter to False.
[23/Jun/2020 14:58:54] "POST /get_gifs/ HTTP/1.1" 500 17874

如果我添加safe=False,它将返回TypeError: Object of type Gif is not JSON serializable

我不明白这一点,因为api_response.data[0]是一本清晰的词典

期望的结果:将Giphy对象记录到Ajax的success函数中

AJAX

(function($) {
  $('#btnSearch').on('click', function(e) {
      var query = $('#search').val();
      console.log(query);
      e.preventDefault();
      $.ajax({
        type: 'post',
        async: true,
        url: '/get_gifs/',
        data: {
          'query': query,
          'csrfmiddlewaretoken': window.CSRF_TOKEN // from blog.html
        },
        success: function(response) {

        },
        error: function(xhr, status, error) {
          // shit happens friends!
        }
    });
  });
}(jQuery));

(插入我的原始-免费-API密钥进行复制)
视图.py

def get_gifs(request):

        # create an instance of the API class
        api_instance = giphy_client.DefaultApi()

        # API Key
        api_key = 'NGSKWrBqtIq1rFU1Ka11D879Y1u4Igia'

        # Search term
        q = request.POST.get('query')
        print(q)

        # Query parameters
        limit = 2
        offset = 0
        rating = 'g'
        lang = 'en'
        fmt = 'json'

        try:
            # Search Endpoint
            api_response = api_instance.gifs_search_get(api_key, q, limit=limit, offset=offset, rating=rating, lang=lang, fmt=fmt)
            pprint(api_response)
        except ApiException as e:
            print("Exception when calling DefaultApi->gifs_search_get: %s\n" % e)

        return JsonResponse(api_response.data[0])

API获取的对象(pprint API\U响应)

{'data': [{'bitly_gif_url': 'https://gph.is/g/EJWjdvN',
           'bitly_url': 'https://gph.is/g/EJWjdvN',
           'content_url': '',
           'create_datetime': None,
           'embed_url': 'https://giphy.com/embed/J0JGg6doLfmV0yZmIB',
           'featured_tags': None,
           'id': 'J0JGg6doLfmV0yZmIB',
           'images': {'downsized': {'height': '250',
                                    'size': '350582',
                                    'url': 'https://media3.giphy.com/media/J0JGg6doLfmV0yZmIB/giphy.gif?cid=ecefd82565bc1664c2b17e3e4b60d88c736d0c6b5a39d682&rid=giphy.gif',
                                    'width': '478'},
                      'downsized_large': {'height': '250',
                                          'size': '350582',
                                          'url': 'https://media3.giphy.com/media/J0JGg6doLfmV0yZmIB/giphy.gif?cid=ecefd82565bc1664c2b17e3e4b60d88c736d0c6b5a39d682&rid=giphy.gif',
                                          'width': '478'},
                      'preview_gif': {'height': '134',
                                      'size': '49623',
                                      'url': 'https://media3.giphy.com/media/J0JGg6doLfmV0yZmIB/giphy-preview.gif?cid=ecefd82565bc1664c2b17e3e4b60d88c736d0c6b5a39d682&rid=giphy-preview.gif',
                                      'width': '256'}},
           'import_datetime': '2020-06-15 10:01:39',
           'is_anonymous': None,
           'is_community': None,
           'is_featured': None,
           'is_hidden': None,
           'is_indexable': None,
           'is_realtime': None,
           'is_removed': None,
           'is_sticker': False,
           'rating': 'g',
           'slug': 'MITEF-mitefarab-asc2020-J0JGg6doLfmV0yZmIB',
           'source': 'www.mitefarab.org',
           'source_post_url': 'www.mitefarab.org',
           'source_tld': '',
           'tags': None,
           'trending_datetime': '0000-00-00 00:00:00',
           'type': 'gif',
           'update_datetime': None,
           'url': 'https://giphy.com/gifs/MITEF-mitefarab-asc2020-J0JGg6doLfmV0yZmIB',
           'user': {'avatar_url': 'https://media2.giphy.com/avatars/MITEF/8FTlysEjtXzx.jpg',
                    'banner_url': '',
                    'display_name': 'MITEF Pan Arab',
                    'profile_url': 'https://giphy.com/MITEF/',
                    'twitter': None,
                    'username': 'MITEF'},
           'username': 'MITEF'},
          {'bitly_gif_url': 'https://gph.is/g/ZdxQQpP',
           'bitly_url': 'https://gph.is/g/ZdxQQpP',
           'content_url': '',
           'create_datetime': None,
           'embed_url': 'https://giphy.com/embed/hTJF0O4vDkJsUi1h8Q',
           'featured_tags': None,
           'id': 'hTJF0O4vDkJsUi1h8Q',
           'images': {'downsized': {'height': '480',
                                    'size': '310971',
                                    'url': 'https://media3.giphy.com/media/hTJF0O4vDkJsUi1h8Q/giphy.gif?cid=ecefd82565bc1664c2b17e3e4b60d88c736d0c6b5a39d682&rid=giphy.gif',
                                    'width': '480'},                      
                      'preview': {'height': '480',
                                  'mp4': 'https://media3.giphy.com/media/hTJF0O4vDkJsUi1h8Q/giphy-preview.mp4?cid=ecefd82565bc1664c2b17e3e4b60d88c736d0c6b5a39d682&rid=giphy-preview.mp4',
                                  'mp4_size': '15536',
                                  'width': '480'},
                      'preview_gif': {'height': '480',
                                      'size': '22387',
                                      'url': 'https://media3.giphy.com/media/hTJF0O4vDkJsUi1h8Q/giphy-preview.gif?cid=ecefd82565bc1664c2b17e3e4b60d88c736d0c6b5a39d682&rid=giphy-preview.gif',
                                      'width': '480'}},
           'import_datetime': '2019-07-19 22:27:40',
           'is_anonymous': None,
           'is_community': None,
           'is_featured': None,
           'is_hidden': None,
           'is_indexable': None,
           'is_realtime': None,
           'is_removed': None,
           'is_sticker': False,
           'rating': 'g',
           'slug': 'RecargaPay-cashback-recargapay-paguetudopelocelular-hTJF0O4vDkJsUi1h8Q',
           'source': 'www.recargapay.com.br',
           'source_post_url': 'www.recargapay.com.br',
           'source_tld': '',
           'tags': None,
           'trending_datetime': '0000-00-00 00:00:00',
           'type': 'gif',
           'update_datetime': None,
           'url': 'https://giphy.com/gifs/RecargaPay-cashback-recargapay-paguetudopelocelular-hTJF0O4vDkJsUi1h8Q',
           'user': {'avatar_url': 'https://media0.giphy.com/avatars/RecargaPay/msKTiPaVkvqd.png',
                    'banner_url': 'https://media0.giphy.com/headers/RecargaPay/kg023vdaAaWA.gif',
                    'display_name': 'RecargaPay',
                    'profile_url': 'https://giphy.com/RecargaPay/',
                    'twitter': None,
                    'username': 'RecargaPay'},
           'username': 'RecargaPay'}],
 'meta': {'msg': 'OK',
          'response_id': '65bc1664c2b17e3e4b60d88c736d0c6b5a39d682',
          'status': 200},
 'pagination': {'count': 2, 'offset': 0, 'total_count': 10}}


Tags: httpscomnoneapiurlgetdatetimeis
3条回答
render(request, template_name, context=None, content_type=None, status=None, using=None)

render() Combines a given template with a given context dictionary and returns an HttpResponse object with that rendered text.

您可以使用Django defaultsJsonResponse类或Django REST frameworkResponse类返回JSON响应

from django.http import JsonResponse
return JsonResponse(data=api_response.data)

from rest_framework.response import Response
return Response(data=api_response.data)

在ipython外壳上试用,效果很好

In [15]: response = Response(api_response.data[0])                                                                                                                              

In [16]: response                                                                                                                                                               
Out[16]: <Response status_code=200, "text/html; charset=utf-8">

response.data给我序列化的响应

Python有一个内置函数,用于将dict转换为json

import json

data = api_response.data
return render(request, json.dumps(data))

如果在return语句中使用它,它应该返回json

我认为您的代码除了视图中的return JsonResponse(api_response.data[0])之外,所有内容都是正确的

JsonResponse

第一个参数data应该是dict实例。如果安全参数设置为False,则它可以是任何JSON可序列化对象official documentation link

当你说

1.safe=True

return JsonResponse(api_response.data[0])

TypeError: In order to allow non-dict objects to be serialized set the safe parameter to False.

错误很明显api_response.data[0]不是dict,请参见第2点错误

2safe=False

return JsonResponse(api_response.data[0], safe=False)
TypeError: Object of type Gif is not JSON serializable

您提供给JsonResponse的数据[0]实际上不是dict类型的对象,这就是第一点出现错误的原因

当您说safe=FalseJsonResponse正在尝试序列化对象,但该对象不可json序列化时,您可以追溯错误

File "....\Python\Python38\lib\json\encoder.py", line 179, in default
    raise TypeError(f'Object of type {o.__class__.__name__} '
TypeError: Object of type Gif is not JSON serializable

可以在link之后查看哪个对象可以Json序列化

回到你的错误上来

因为api_response.data[0]是一本水晶般清晰的字典,所以我不明白这一点

api_responseapi_response.data[0]的类型

type(api_response)
<class 'giphy_client.models.inline_response_200.InlineResponse200'>
type(api_response.data[0])
<class 'giphy_client.models.gif.Gif'>

您可以按照giphy_clientdocumentation link了解更多详细信息

解决方案

result = api_response.data[0].to_dict()   ## NOTE to_dict function of giphy_client.models.gif.Gif

return JsonResponse(result)

相关问题 更多 >