AssertionError: 302 != 200 : Не удалось получить страницу перенаправления '/api/v2/app/nextdialog': код ответа был 302 (ожидалось 200)

AssertionError: 302 != 200 : Не удалось получить страницу перенаправления '/api/v2/app/nextdialog': код ответа был 302 (ожидалось 200)

В DJango возможно ли иметь три вида, каждый из которых перенаправляет на следующий. Вид 1 перенаправляет на вид 2, а вид 2 перенаправляет на вид 3?

Views.py:

class ConversationLayerView(generics.GenericAPIView):
    permission_classes = (permissions.IsAuthenticated,)

    def post(self, request, *args, **kwargs):
        body = request.data
        cardType = body["cardType"]
        if cardType == "CHOICE":
            serializer = appChoiceTypeSerializer(body)
        elif cardType == "TEXT":
            serializer = appTextTypeSerializer(body)
        elif cardType == "INPUT":
            serializer = appInputTypeSerializer(body)
        else:
            serializer = StartAssessmentSerializer(body)
        validated_body = serializer.validate_value(body)
        url = get_endpoint(validated_body)
        reverse_url = encodeurl(body, url)
        return HttpResponseRedirect(reverse_url)
        

class NextDialog(generics.GenericAPIView):
    permission_classes = (permissions.AllowAny,)

    def get(self, request, *args, **kwargs):
        result = request.GET
        data = result.dict()
        contact_uuid = data["contact_uuid"]
        step = data["step"]
        value = data["value"]
        description = data["description"]
        title = data["title"]

        if data["cardType"] == "CHOICE":
            optionId = int(value) - 1
        else:
            optionId = data["optionId"]
        path = get_path(data)
        assessment_id = path.split("/")[-3]
        request = build_rp_request(data)
        app_response = post_to_app(request, path)
        if data["cardType"] != "TEXT":
            if data["cardType"] == "INPUT":
                optionId = None
            store_url_entry = appAssessments(
                contact_id=contact_uuid,
                assessment_id=assessment_id,
                title=title,
                description=description,
                step=step,
                user_input=value,
                optionId=optionId,
            )
            store_url_entry.save()
        pdf = pdf_ready(app_response)
        if pdf:
            response = pdf_endpoint(app_response)
            return HttpResponseRedirect(response)
        else:
            message = format_message(app_response)
            return Response(message, status=status.HTTP_200_OK)
            
            
class Reports(generics.GenericAPIView):
    permission_classes = (permissions.AllowAny,)

    def get(self, request, *args, **kwargs):
        report_id = request.GET.get("report_id")
        response = get_report(report_id)
        return Response(response, status=status.HTTP_200_OK)                    
        
    

Utils.py

def get_endpoint(payload):
   value = payload["value"]
   if value != "":
       if value == "back":
           url = reverse("app-previous-dialog")
       elif value == "abort":
           url = reverse("app-abort")
       else:
           url = reverse("app-next-dialog")
   elif value == "":
       url = reverse("app-start-assessment")
   return url

def encodeurl(payload, url):
   qs = "?" + urlencode(payload, safe="")
   reverse_url = url + qs
   return reverse_url

Пояснение кода: Приложение получает json полезную нагрузку в ConversationLayerView. Оно вызывает метод конечной точки, чтобы узнать, на какую конечную точку перенаправлять, основываясь на значении ключа 'value' в полезной нагрузке.

Запрос выглядит примерно так:

            "contact_uuid": "67460e74-02e3-11e8-b443-00163e990bdb",
            "choices": null,
            "value": "Charles",
            "cardType": "INPUT",
            "step": null,
            "optionId": null,
            "path": "",
            "title": "",
            "description": "What's your name",
            "message": ""
        }

Поскольку "value" равно "Charles", представление перенаправляется на "app-next-dialog" в представлении NextDialog. В этом представлении выполняется POST-запрос к внешнему приложению и получается json-ответ. Если в ответе есть ключ PDF, это представление перенаправляет на третье представление. Это происходит следующим образом:

if pdf:
            response = pdf_endpoint(app_response)
            return HttpResponseRedirect(response)
        else:
            message = format_message(app_response)
            return Response(message, status=status.HTTP_200_OK)

Если ключ присутствует, то перенаправьте на "response", чей вывод "/api/v2/app/reports?report_id=/reports/17340f51604cb35bd2c6b7b9b16f3aec", иначе не перенаправляйте, а верните 200.

Ошибка:

AssertionError: 302 != 200 : Couldn't retrieve redirection page '/api/v2/app/nextdialog': response code was 302 (expected 200)

Url.py

path(
        "api/v2/ada/assessments",
        views.PresentationLayerView.as_view(),
        name="ada-assessments",
    ),
    ),
    path("api/v2/ada/nextdialog", views.NextDialog.as_view(), name="ada-next-dialog"),
    path("api/v2/ada/reports", views.Reports.as_view(), name="ada-reports"),

Пока что это не работает. В общем, я просто пытаюсь начать с вида 1, перенаправить на вид 2 и перенаправить на вид 3 с вида 2. Возможно ли это в Django? Спасибо.

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

assertRedirects проверяет статус ответа, и по умолчанию требует, чтобы это был ответ HTTP 200. Поскольку у вас есть цепочка перенаправлений, ответом является 302 (еще одно перенаправление), а не 200, поэтому тест проваливается с ошибкой "response code was 302 (expected 200)".

Вам необходимо изменить аргумент target_status_code, чтобы сообщить assertRedirects, что вы ожидаете от ответа код состояния 302:

self.assertRedirects(response, self.destination_url, target_status_code=302)
Вернуться на верх