Доступная для просмотра оболочка API Django REST для внешних вызовов API

#python #json #django #django-rest-framework #python-requests

#python #json #django #django-rest-framework #python-запросы

Вопрос:

Я создаю интерфейс RESTful для проекта Django, и мне нужно использовать внешние API, чтобы клиент и интерфейс могли ссылаться только на один API Django, не требуя подробностей о внешних API.

Поэтому я хочу, чтобы данные внешнего API возвращались на страницы API, доступные для просмотра, так же, как я бы использовал свой собственный API на основе представления.

Как мне сериализовать ответ JSON из внешнего API в средство визуализации веб-страницы с возможностью просмотра API?

Например, я хочу, чтобы mysite.fake/thing/details возвращал тот же JSON, который возвращается externalapi.fake/thing/details , который выглядит как:

 {"thing_id": "900404", "description": "Thing description", "value": "100.00", "location": "Bin 401"}
  

И это должно отображаться в доступном для просмотра API для DRF.

В настоящее время я использую:

 @api_view(('GET',))
@renderer_classes((JSONRenderer,))
def thing_finder(request, thing_id):
    """
    Get the current location for a thing
    http://localhost:8000/thing/find/9900404
    :param request: HTTP Request object
    :param thing_id: String - the thing ID
    :return: JSON - The Thing location JSON
    """
    a, b = THING_API_AUTH
    if request.method == 'GET':
        payload = {'thing_id': thing_id}
        r = requests.get(THING_API_AUTH, auth=HTTPBasicAuth(a, b), params=payload)
        if r.status_code == 200:
            data = json.loads(r.text)
            serializer = ThingFinderSerializer(data)
            return Response(serializer.data, status=status.HTTP_200_OK)
        else:
            return Response({"error": "Request failed"}, status=r.status_code)
  

В settings.py я включаю:

 REST_FRAMEWORK = {
    'DEFAULT_RENDERER_CLASSES': [
        'rest_framework.renderers.JSONRenderer',
        'rest_framework.renderers.BrowsableAPIRenderer',
    ]
}
  

Это работает (я думаю), но не форматирует результаты в доступный для просмотра API. Вместо этого я получаю неформатированную страницу с выгруженным на нее JSON. Я пропустил требование к шаблону? Неправильный URL-адрес в браузере? BrowsableAPIRenderer settings.py Недостаточно ли для рендеринга по умолчанию для просматриваемого API? TIA.

Ответ №1:

Здесь вам не нужно использовать сериализатор в качестве внешнего источника, возвращающего данные JSON. Вы можете использовать response.json() метод как

 @api_view(('GET',))
@renderer_classes((JSONRenderer,))
def thing_finder(request, thing_id):
    a, b = THING_API_AUTH
    if request.method == 'GET':
        payload = {
            'thing_id': thing_id
        }
        response = requests.get(
            THING_API_AUTH,
            auth=HTTPBasicAuth(a, b),
            params=payload
        )
        if response.status_code == 200:
            return Response(response.json(), status=status.HTTP_200_OK)
        return Response({"error": "Request failed"}, status=response.status_code)  

Комментарии:

1. Я пытаюсь получить ответ для рендеринга в доступном для просмотра API DRF — если я использую ваш метод, я получаю ту же страницу без стиля, только с возвращением необработанного JSON. Но это хороший совет только для необработанного JSON.

2. Тогда какой формат вы ожидаете? покажите некоторый пример

3. Форматированный рендеринг, подобный этому: django-rest-framework.org/api-guide/renderers /…

4. Я не понимаю, в чем разница. Возможно, добавление скриншота или изображения может помочь (мне) понять ситуацию

5. Я решил это — мне нужно было включить декоратор BrowsableAPIRenderer вместе с JSONRenderer. Спасибо

Ответ №2:

Я решил это:

 from rest_framework.renderers import JSONRenderer, BrowsableAPIRendererenter
@api_view(('GET',))
@renderer_classes((JSONRenderer, BrowsableAPIRenderer))
def thing_finder(request, thing_id):
    """
    Get the current location for a thing
    http://localhost:8000/thing/find/9900404
    :param request: HTTP Request object
    :param thing_id: String - the thing ID
    :return: JSON - The Thing location JSON
    """
    a, b = THING_API_AUTH
    if request.method == 'GET':
        payload = {'thing_id': thing_id}
        r = requests.get(THING_API_AUTH, auth=HTTPBasicAuth(a, b), params=payload)
        if r.status_code == 200:
            data = json.loads(r.text)
            serializer = ThingFinderSerializer(data)
            return Response(serializer.data, status=status.HTTP_200_OK)
        else:
            return Response({"error": "Request failed"}, status=r.status_code)
  

Это возвращает доступную для просмотра визуализацию API в виде чистой, отформатированной страницы.