在Django中使用Python的HTTPStatus两种方法

301 阅读2分钟

魔术数字 "是一种反模式,即直接使用一个数字,而不是将其存储在一个描述性的变量名中。 在网页代码中,HTTP 状态代码经常被用作魔术数字,也许是因为网页开发者记住了常见的代码,如 200 和 404。 在 Python 中,我们可以通过标准库的http.HTTPStatus 枚举的描述性引用来避免这种魔术。

让我们看看在我们的Django代码中使用HTTPStatus 的两种方法。

1.创建响应

Django包含了一堆针对常见状态代码的 HttpResponse 子类,但这个列表是故意不详尽的。如果我们需要返回一个不存在类的状态代码,我们可以使用Python的HTTPStatus 与Django的HttpResponse

例如,如果我们的一个页面由于法律原因而不可用,所以我们想返回状态码451。我们可以像这样用HttpResponse

from http import HTTPStatus

from django.http import HttpResponse


def taken_down(request):
    ...
    return HttpResponse(
        content,
        status_code=HTTPStatus.UNAVAILABLE_FOR_LEGAL_REASONS,
    )

如果我们发现自己在项目中经常使用一个状态码,我们可以创建自己的HttpResponse 子类,就像文档中提到的那样。 例如。

from http import HTTPStatus

from django.http import HttpResponse


class HttpResponseLegallyUnavailable(HttpResponse):
    status_code = HTTPStatus.UNAVAILABLE_FOR_LEGAL_REASONS

此外,当使用Django的render() 快捷方式时,我们可以用status 参数来改变状态码。

from http import HTTPStatus

from django.shortcuts import render


def taken_down(request):
    ...
    return render(
        request,
        "illegal.html",
        status=HTTPStatus.UNAVAILABLE_FOR_LEGAL_REASONS,
    )

2.在测试断言中

在使用Django的测试客户端时,我们通常会对响应状态码进行断言。 这种断言也可以用HTTPStatus

from http import HTTPStatus

from django.test import TestCase


class IndexTests(TestCase):
    def test_success(self):
        response = self.client.get("/")

        self.assertEqual(response.status_code, HTTPStatus.OK)
        ...


class TakenDownTests(TestCase):
    def test_success(self):
        response = self.client.get("/some-taken-down-page/")

        self.assertEqual(
            response.status_code,
            HTTPStatus.UNAVAILABLE_FOR_LEGAL_REASONS,
        )
        ...

rest_framework.status

Django REST框架在其rest_framework.status 模块中也有类似的结构,它比http.HTTPStatus 更早。这不是一个枚举,而是一个包含数字常数的模块,如HTTP_200_OK

我推荐你使用http.HTTPStatus ,而不是rest_framework.status ,原因有以下几点。

  1. 它是标准库的一部分,你可以在任何项目中使用它,而不仅仅是使用Django REST框架的项目。
  2. 它有更多的数据:每个状态代码都有其原因短语和描述。
  3. 作为一个枚举,它是一个独立的类型,int ,这对于比较、调试和类型检查很有用。