python - AssertionError : 302 ! = 200:无法检索重定向页面 '/api/v2/app/nextdialog':响应代码为302(预期为200)

标签 python python-3.x django redirect django-views

断言错误:302!= 200:无法检索重定向页面“/api/v2/app/nextdialog”:响应代码为 302(预期为 200)

在 Django 中,可以有三个 View ,每个 View 都重定向到下一个 View 。 View 1 重定向到 View 2, View 2 重定向到 View 3?

View .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

代码解释: 应用程序在 ConversationLayerView 中接收 json 负载。它调用端点方法来根据负载中设置的“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”,因此 View 将重定向到 NextDialog View 中的“app-next-dialog”。 在此 View 中,向外部应用程序发出 POST 请求并收到 json 响应。如果响应具有 PDF key ,则此 View 将重定向到第三个 View 。 这发生在这里:

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

如果 key 存在,则重定向到“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)

网址.py

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

test_views.py:

class appAssessmentReport(APITestCase):
    data = {
        "contact_uuid": "67460e74-02e3-11e8-b443-00163e990bdd",
        "choices": None,
        "message": (
            "How old are you?\n\nReply *back* to go to "
            "the previous question or *abort* to "
            "end the assessment"
        ),
        "explanations": "",
        "step": 39,
        "value": "27",
        "optionId": None,
        "path": "/assessments/f9d4be32-78fa-48e0-b9a3-e12e305e73ce/dialog/next",
        "cardType": "INPUT",
        "title": "Patient Information",
        "description": "How old are you?",
    }

    start_url = reverse("app-assessments")
    next_dialog_url = reverse("app-next-dialog")
    pdf_url = reverse("app-reports")
    
    destination_url = (
        "/api/v2/app/nextdialog?contact_uuid="
        "67460e74-02e3-11e8-b443-00163e990bdd&"
        "choices=None&message=How+old+are+you%3F"
        "%0A%0AReply+%2Aback%2A+to+go+to+the+"
        "previous+question+or+%2Aabort%2A+to+end"
        "+the+assessment&explanations=&step="
        "39&value=27&optionId=None&path=%2F"
        "assessments%2Ff9d4be32-78fa-48e0-b9a3"
        "-e12e305e73ce%2Fdialog%2Fnext&cardType"
        "=INPUT&title=Patient+Information&"
        "description=How+old+are+you%3F"
    )
    
    @patch("app.views.pdf_ready")
    @patch("app.views.post_to_app")
    def test_assessment_report(self, mock_post_to_app, mock_pdf_ready):
        mock_post_to_app.return_value = {
            "cardType": "CHOICE",
            "step": 40,
            "title": {"en-US": "YOUR REPORT"},
            "description": {"en-US": ""},
            "options": [
                {"optionId": 0, "text": {"en-US": "Option 1"}},
                {"optionId": 1, "text": {"en-US": "Option 2"}},
                {"optionId": 2, "text": {"en-US": "Option 3"}},
            ],
            "_links": {
                "self": {
                    "method": "GET",
                    "href": "/assessments/898d915e-229f-48f2-9b98-cfd760ba8965",
                },
                "report": {
                    "method": "GET",
                    "href": "/reports/17340f51604cb35bd2c6b7b9b16f3aec",
                },
            },
        }
        mock_pdf_ready.return_value = utils.pdf_ready(mock_post_to_app.return_value)
        user = get_user_model().objects.create_user("test")
        self.client.force_authenticate(user)
        response = self.client.post(self.start_url, self.data, format="json")
        print(response)
        self.assertRedirects(response, self.destination_url)

到目前为止这还不起作用。总之,我只是尝试从 View 1 开始,重定向到 View 2,然后从 View 2 重定向到 View 3。 这在 Django 中可能吗? 谢谢。

最佳答案

问题在于您的测试,而不是 View 逻辑 - 完全有可能存在一系列重定向。

assertRedirects 检查响应的状态,默认情况下要求它是 HTTP 200 响应。由于您有一系列重定向,因此响应为 302(另一个重定向)而不是 200,这就是测试失败并显示错误“响应代码为 302(预期为 200)”的原因。

您需要修改target_status_code告诉 assertRedirects 您期望响应包含 302 状态代码的参数:

self.assertRedirects(response, self.destination_url, target_status_code=302)

关于python - AssertionError : 302 ! = 200:无法检索重定向页面 '/api/v2/app/nextdialog':响应代码为302(预期为200),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71919799/

相关文章:

python - 预填充 BooleanField 已选中 (WTForms)

python - 通过我的 Django 模型访问选择

mysql.connector+mysql 在获取时挂起

python - 无法在 Python 3 中从 G Suite 获取用户

Django 测试非字段验证错误

python - 为 Selenium 创建用于单击下拉菜单的 Xpath

Python subprocess.call() 显然不适用于 psexec

python - 对满足嵌套键中的条件的字典的所有值进行操作

python - 在 django-profile 中添加字段 first_name 和 last_name

python - Django 找不到我的自定义模板过滤器