编写视图¶
一个视图函数(或简称为视图)是一个 Python 函数,它接受 Web 请求并返回一个 Web 响应。这个响应可以是 Web 页面的 HTML 内容,或者重定向,或者404错误,或者 XML 文档,或一个图片...或是任何内容。视图本身包含返回响应所需的任何逻辑。这个代码可以存在任何地方,只要它在你的 Python 路径上就行。可以说,不需要其他东西,这里并没有魔法。为了将代码放置在某处,约定将视图放在名为views.py
的文件里,这个文件放置在项目或应用目录里。
一个简单的视图¶
这里是一个以 HTML 文档形式返回当前日期和时间的视图:
fromdjango.httpimportHttpResponseimportdatetimedefcurrent_datetime(request):now=datetime.datetime.now()html="<html><body>It is now%s.</body></html>"%nowreturnHttpResponse(html)
让我们来完成这个代码:
首先,我们从
django.http
模块导入类HttpResponse
,以及 Python 的datetime
库。然后,我们定义一个名为
current_datetime
的函数。这是一个视图函数。每个视图函数都将HttpRequest
对象作为第一个参数,通常名为request
。注意视图函数名称无关紧要;它不需要以特定的名称来让 Django 识别它。我们在这里命名
current_datetime
,因为这个名字可以清楚的表示它的用途。视图返回一个包含生成的响应的
HttpResponse
对象。每个视图函数都要返回HttpResponse
对象。(有例外,我们稍后再讲)
Django 时区
Django 包含TIME_ZONE
设置,默认是America/Chicago
。你可以在配置文件里改成你所在的时区。
返回错误信息¶
Django 提供了有关返回 HTTP 错误代码的帮助。HttpResponse
的子类除了200外,还有很多常见的 HTTP 状态代码。你可以在request/response 文档中找到所有可用子类的列表。返回这些子类中某个子类的实例而不是HttpResponse
来表示错误。比如:
fromdjango.httpimportHttpResponse,HttpResponseNotFounddefmy_view(request):# ...iffoo:returnHttpResponseNotFound('<h1>Page not found</h1>')else:returnHttpResponse('<h1>Page was found</h1>')
并不是每个可用 HTTP 响应代码都有专门指定的子类,因为它们很多并不常见。然而,如HttpResponse
文档中所述的那样,你也可以将 HTTP 状态代码传递给HttpResponse
的构造函数,这样就可以为任何状态代码创建返回类。比如:
fromdjango.httpimportHttpResponsedefmy_view(request):# ...# Return a "created" (201) response code.returnHttpResponse(status=201)
因为 404 错误是最常见的 HTTP 错误,这里有更简单的方法来处理这些错误。
Http404
异常¶
- class
django.http.
Http404
¶
当你返回错误,例如HttpResponseNotFound
,你需要定义错误页面的 HTML 。
returnHttpResponseNotFound('<h1>Page not found</h1>')
为方便起见,在你的网站里有个一致的 404 错误页面是个好办法,Django 提供Http404
异常。如果你在视图的任何地方引发了Http404
,Django 会捕捉到它并且返回标准的错误页面,连同 HTTP 错误代码 404 。
用法示例:
fromdjango.httpimportHttp404fromdjango.shortcutsimportrenderfrompolls.modelsimportPolldefdetail(request,poll_id):try:p=Poll.objects.get(pk=poll_id)exceptPoll.DoesNotExist:raiseHttp404("Poll does not exist")returnrender(request,'polls/detail.html',{'poll':p})
为了在 Django 返回404时显示自定义的 HTML,你可以创建名为404.html
的HTML模板,并将其放置在你的模板树顶层。这个模板将在DEBUG
设为False
时提供。
当DEBUG
为True
时,你可以提供Http404
信息,并且在标准的 404 调试模板里显示。使用这些信息来调试;它们通常不适合在生产环境下的404模板。
自定义报错视图¶
Django 里默认的报错视图应该能满足大部分的 Web 应用,但你也可以很方便的自定义。指定处理程序,如下方所示。(在其他地方配置它不会有任何效果)。
可以用handler404
: 覆盖page_not_found()
视图:
handler404='mysite.views.my_custom_page_not_found_view'
可以用handler500
: 覆盖server_error()
视图:
handler500='mysite.views.my_custom_error_view'
可以用handler403
: 覆盖permission_denied()
视图:
handler403='mysite.views.my_custom_permission_denied_view'
可以用handler400
: 覆盖bad_request()
视图:
handler400='mysite.views.my_custom_bad_request_view'
参见
使用CSRF_FAILURE_VIEW
来覆盖 CSRF 报错视图。
测试自定义报错视图¶
为了测试自定义报错处理的响应,可以适当地在测试视图里引发异常。例如:
fromdjango.core.exceptionsimportPermissionDeniedfromdjango.httpimportHttpResponsefromdjango.testimportSimpleTestCase,override_settingsfromdjango.urlsimportpathdefresponse_error_handler(request,exception=None):returnHttpResponse('Error handler content',status=403)defpermission_denied_view(request):raisePermissionDeniedurlpatterns=[path('403/',permission_denied_view),]handler403=response_error_handler# ROOT_URLCONF must specify the module that contains handler403 = ...@override_settings(ROOT_URLCONF=__name__)classCustomErrorHandlerTests(SimpleTestCase):deftest_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 的asyncdef
语法定义。Django 会自动检测这些函数,并在异步上下文中运行它们。但是,你需要使用基于 ASGI 的异步服务器来获得它们的性能优势。
下面是一个异步视图的例子:
importdatetimefromdjango.httpimportHttpResponseasyncdefcurrent_datetime(request):now=datetime.datetime.now()html='<html><body>It is now%s.</body></html>'%nowreturnHttpResponse(html)
你可以在异步支持 中阅读更多关于 Django 的异步支持,以及如何最好的使用异步视图。