魔术数字 "是一种反模式,即直接使用一个数字,而不是将其存储在一个描述性的变量名中。 在网页代码中,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 ,原因有以下几点。
- 它是标准库的一部分,你可以在任何项目中使用它,而不仅仅是使用Django REST框架的项目。
- 它有更多的数据:每个状态代码都有其原因短语和描述。
- 作为一个枚举,它是一个独立的类型,
int,这对于比较、调试和类型检查很有用。