编写视图¶
视图函数,简称视图,是一个 Python 函数,它接收一个 Web 请求并返回一个 Web 响应。此响应可以是网页的 HTML 内容,也可以是重定向、404 错误、XML 文档、图像……实际上,任何内容都可以。视图本身包含返回该响应所需的任何任意逻辑。此代码可以放在任何你想要的地方,只要它在你的 Python 路径上即可。没有其他要求——可以说没有“魔法”。为了将代码放在某个地方,约定将视图放在名为views.py
的文件中,该文件位于你的项目或应用程序目录中。
简单的视图¶
这是一个返回当前日期和时间(作为 HTML 文档)的视图
from django.http import HttpResponse
import datetime
def current_datetime(request):
now = datetime.datetime.now()
html = '<html lang="en"><body>It is now %s.</body></html>' % now
return HttpResponse(html)
让我们逐行分析这段代码
首先,我们从
django.http
模块导入HttpResponse
类,以及 Python 的datetime
库。接下来,我们定义一个名为
current_datetime
的函数。这是视图函数。每个视图函数都将HttpRequest
对象作为其第一个参数,通常命名为request
。请注意,视图函数的名称无关紧要;它不必以某种方式命名才能被 Django 识别。我们在这里将其命名为
current_datetime
,因为该名称清楚地表明了它的作用。视图返回一个包含生成的响应的
HttpResponse
对象。每个视图函数都负责返回一个HttpResponse
对象。(有一些例外,但我们稍后会讨论。)
Django 的时区
Django 包含一个TIME_ZONE
设置,默认为America/Chicago
。这可能不是你的所在地,因此你可能需要在设置文件中更改它。
将 URL 映射到视图¶
因此,概括地说,此视图函数返回一个包含当前日期和时间的 HTML 页面。要在特定 URL 上显示此视图,你需要创建一个URLconf;有关说明,请参阅URL 分发器。
返回错误¶
Django 提供了返回 HTTP 错误代码的帮助。对于除 200(表示“OK”)以外的许多常用 HTTP 状态代码,都有HttpResponse
的子类。你可以在请求/响应文档中找到可用子类的完整列表。返回这些子类之一的实例而不是普通的HttpResponse
以表示错误。例如
from django.http import HttpResponse, HttpResponseNotFound
def my_view(request):
# ...
if foo:
return HttpResponseNotFound("<h1>Page not found</h1>")
else:
return HttpResponse("<h1>Page was found</h1>")
并非所有可能的 HTTP 响应代码都有专门的子类,因为许多代码并不常见。但是,如HttpResponse
文档中所述,你还可以将 HTTP 状态代码传递到HttpResponse
的构造函数中,以创建你喜欢的任何状态代码的返回类。例如
from django.http import HttpResponse
def my_view(request):
# ...
# Return a "created" (201) response code.
return HttpResponse(status=201)
由于 404 错误是迄今为止最常见的 HTTP 错误,因此有一种更简单的方法来处理这些错误。
Http404
异常¶
- class django.http.Http404¶
当你返回HttpResponseNotFound
之类的错误时,你负责定义生成的错误页面的 HTML
return HttpResponseNotFound("<h1>Page not found</h1>")
为方便起见,并且因为在整个站点上拥有始终如一的 404 错误页面是个好主意,所以 Django 提供了一个Http404
异常。如果你在视图函数中的任何点引发Http404
,Django 将捕获它并返回应用程序的标准错误页面,以及 HTTP 错误代码 404。
用法示例
from django.http import Http404
from django.shortcuts import render
from polls.models import Poll
def detail(request, poll_id):
try:
p = Poll.objects.get(pk=poll_id)
except Poll.DoesNotExist:
raise Http404("Poll does not exist")
return render(request, "polls/detail.html", {"poll": p})
为了在 Django 返回 404 时显示自定义 HTML,你可以在模板树的顶层创建一个名为404.html
的 HTML 模板。当DEBUG
设置为False
时,将提供此模板。
当DEBUG
为True
时,你可以向Http404
提供消息,它将出现在标准 404 调试模板中。将这些消息用于调试目的;它们通常不适合用于生产 404 模板。
自定义错误视图¶
Django 中的默认错误视图应该足以满足大多数 Web 应用程序的需求,但是如果你需要任何自定义行为,可以轻松地覆盖它们。如下所示在你的 URLconf 中指定处理程序(在其他任何地方设置它们都不会有任何效果)。
page_not_found()
视图被handler404
覆盖
handler404 = "mysite.views.my_custom_page_not_found_view"
handler500 = "mysite.views.my_custom_error_view"
permission_denied()
视图被handler403
覆盖
handler403 = "mysite.views.my_custom_permission_denied_view"
handler400 = "mysite.views.my_custom_bad_request_view"
另请参阅
使用CSRF_FAILURE_VIEW
设置来覆盖 CSRF 错误视图。
测试自定义错误视图¶
要测试自定义错误处理程序的响应,请在测试视图中引发相应的异常。例如
from django.core.exceptions import PermissionDenied
from django.http import HttpResponse
from django.test import SimpleTestCase, override_settings
from django.urls import path
def response_error_handler(request, exception=None):
return HttpResponse("Error handler content", status=403)
def permission_denied_view(request):
raise PermissionDenied
urlpatterns = [
path("403/", permission_denied_view),
]
handler403 = response_error_handler
# ROOT_URLCONF must specify the module that contains handler403 = ...
@override_settings(ROOT_URLCONF=__name__)
class CustomErrorHandlerTests(SimpleTestCase):
def test_handler_renders_template_response(self):
response = self.client.get("/403/")
# Make assertions on the response here. For example:
self.assertContains(response, "Error handler content", status_code=403)
异步视图¶
除了同步函数之外,视图还可以是异步(“async”)函数,通常使用 Python 的async def
语法定义。Django 将自动检测这些函数并在异步上下文中运行它们。但是,你需要使用基于 ASGI 的异步服务器才能获得它们的性能优势。
这是一个异步视图的示例
import datetime
from django.http import HttpResponse
async def current_datetime(request):
now = datetime.datetime.now()
html = '<html lang="en"><body>It is now %s.</body></html>' % now
return HttpResponse(html)
你可以在异步支持中阅读更多关于 Django 异步支持以及如何最好地使用异步视图的信息。