Django - 视图函数
视图函数,或简称视图,是一种接受 Web 请求并返回 Web 响应的 Python 函数。 这个响应可以是网页的 HTML 内容,也可以是重定向,也可以是 404 错误,也可以是 XML 文档,也可以是图像. . . 或任何东西,真的。 视图本身包含返回该响应所需的任意逻辑。 此代码可以位于您想要的任何位置,只要它在您的 Python 路径上即可。 没有其他要求 —— 没有“魔法”,可以这么说。 为了将代码放在某个地方,约定是将视图放在一个名为 views.py
的文件中,该文件位于您的项目或应用程序目录中。
简单示例
这里是一个以 HTML 文档形式返回当前日期和时间的视图:
1 | from django.http import HttpResponse |
- 首先,我们从
django.http
模块导入类HttpResponse
,以及 Python 的datetime
库。 - 然后,我们定义一个名为
current_datetime
的函数。这是一个视图函数。每个视图函数都将HttpRequest
对象作为第一个参数,通常名为request
。- 注意:视图函数名称无关紧要;它不需要以特定的名称来让 Django 识别它。我们在这里命名
current_datetime
,因为这个名字可以清楚的表示它的用途。
- 注意:视图函数名称无关紧要;它不需要以特定的名称来让 Django 识别它。我们在这里命名
- 视图返回一个包含生成的响应的
HttpResponse
对象。每个视图函数都要返回HttpResponse
对象。(有例外,我们稍后再讲)
-
属相
-
scheme
代表请求协议的字符串(通常是
http
或https
)。 -
path
表示请求页面的完整路径的字符串,不包括方案、域或查询字符串。
-
method
代表请求中使用的 HTTP 方法的字符串。保证是大写字母。
-
GET
一个类似字典的对象,包含所有给定的 HTTP GET 参数。参见下面的
QueryDict
文档。 -
POST
一个类似字典的对象,包含所有给定的 HTTP POST 参数,前提是请求包含表单数据。参见下面的
QueryDict
文档。如果你需要访问请求中发布的原始或非表单数据,可以通过HttpRequest.body
属性来访问。 -
COOKIES
一个包含所有 cookies 的字典。键和值是字符串。
-
FILES
- 一个类似字典的对象,包含所有上传的文件。
FILES
中的每个键是<input type="file" name="">
中的name
。FILES
中的每个值是一个UploadedFile
。更多信息请参见 管理文件。 FILES
只有在请求方法是 POST,并且发布请求的<form>
有enctype="multipart/form-data"
的情况下,才会包含数据。否则,FILES
将是一个类似字典的空白对象。
- 一个类似字典的对象,包含所有上传的文件。
-
META
一个包含所有可用的 HTTP 头文件的字典。可用的头信息取决于客户端和服务器,部分示例:
CONTENT_LENGTH
—— 请求体的长度(字符串)。CONTENT_TYPE
—— 请求体的 MIME 类型。HTTP_ACCEPT
—— 可接受的响应内容类型。HTTP_ACCEPT_ENCODING
—— 可接受的响应编码。HTTP_ACCEPT_LANGUAGE
—— 可接受的响应语言。HTTP_HOST
—— 客户端发送的 HTTP 主机头。HTTP_REFERER
—— referrer 页面,如果有的话。HTTP_USER_AGENT
—— 客户端的用户代理字符串。QUERY_STRING
—— 查询字符串,是一个单一的(未解析的)字符串。REMOTE_ADDR
—— 客户机的 IP 地址。REMOTE_HOST
—— 客户机的主机名。REMOTE_USER
– The user authenticated by the web server, if any.REQUEST_METHOD
——"GET"
或"POST"
等字符串。SERVER_NAME
—— 服务器的主机名。SERVER_PORT
—— 服务器的端口(字符串)。
-
headers
一个不区分大小写的类似字典的对象,提供对请求中所有 HTTP 前缀头的访问(加上
Content-Length
和Content-Type
)。
-
-
方法
-
get_host()
使用
HTTP_X_FORWARDED_HOST
(如果USE_X_FORWARDED_HOST
已启用)和HTTP_HOST
头信息,按顺序返回请求的发起主机。如果它们没有提供一个值,则该方法使用SERVER_NAME
和SERVER_PORT
的组合,详见 PEP 3333。 -
get_port()
使用
HTTP_X_FORWARDED_PORT
(如果USE_X_FORWARDED_PORT
已启用)和SERVER_PORT
META
变量中的信息,按顺序返回请求的起始端口。 -
is_ajax()
- 是否是 ajax 请求,该方法于Django 3.1中已被 废弃,因为它依赖于 jQuery 特定的方式来表示 AJAX 调用,而当前的用法倾向于使用 JavaScript Fetch API 。根据你的用例,你可以写你自己的 AJAX 检测方法,或者使用新的
HttpRequest.accepts()
方法,如果你的代码依赖于客户端Accept
HTTP 头。 - 如果你正在编写自己的 AJAX 检测方法,
request.is_ajax()
可以完全复制为request.headers.get('x-requested-with') == 'XMLHttpRequest'
。
- 是否是 ajax 请求,该方法于Django 3.1中已被 废弃,因为它依赖于 jQuery 特定的方式来表示 AJAX 调用,而当前的用法倾向于使用 JavaScript Fetch API 。根据你的用例,你可以写你自己的 AJAX 检测方法,或者使用新的
-
accepts(mime_type)
如果请求的
Accept
头符合mime_type
参数,则返回True
。1
2'text/html') request.accepts(
True
-
-
示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14from django.http import HttpResponse
def index(request):
print(request.path)
print(request.method)
# print(request.is_ajax())
print(request.accepts('text/html'))
print(request.scheme)
print(request.GET)
print(request.POST)
print(request.FILES)
print(request.get_host())
print(request.META.get('REMOTE_ADDR'))
return HttpResponse('<h1>商品首页面</h1>')
-
概述
- 与 Django 自动创建的
HttpRequest
对象不同,HttpResponse
对象是你的责任。你写的每个视图都要负责实例化、填充和返回一个HttpResponse
对象。 HttpResponse
类位于django.http
模块中。
- 与 Django 自动创建的
-
render()
-
概述
- 将给定的模板与给定的上下文字典组合在一起,并以渲染的文本返回一个
HttpResponse
对象。 - Django没有提供返回
TemplateResponse
的便捷函数,因为TemplateResponse
的构造函数提供了与render()
同等程度的便利。
- 将给定的模板与给定的上下文字典组合在一起,并以渲染的文本返回一个
-
参数
-
示例
1
2
3
4from django.shortcuts import render
def show_goods1(request):
return render(request, 'goods/goods.html')
-
-
redirect()
-
概述
- 返回一个
HttpResponseRedirect
,指向传递参数的适当 URL。 - 参数可以是:
- 一个模型:模型的
get_absolute_url()
函数将被调用。 - 视图名,可能带有的参数:
reverse()
将被用于反向解析名称。 - 一个绝对或相对 URL,将按原样用作重定向位置。
- 一个模型:模型的
- 返回一个
-
示例
-
传递对象,对象的
get_absolute_url()
方法将被调用来指向重定向地址1
2
3
4
5
6from django.shortcuts import redirect
def my_view(request):
...
obj = MyModel.objects.get(...)
return redirect(obj) -
传递视图名和一些可选的位置或关键字参数;URL 将使用
reverse()
方法来反向解析1
2
3
4
5
6
7
8def my_view(request):
...
return redirect('some-view-name', foo='bar')
def login(request):
...
return redirect(reverse('user:show'))
return redirect('user:show') -
传递绝对或相对 URL 来重定向
1
2
3
4
5
6
7
8
9# 传递相对URL
def my_view(request):
...
return redirect('/some/url/')
# 传递绝对URL
def my_view(request):
...
return redirect('https://example.com/')
-
-
默认情况下,
redirect()
返回临时重定向。所有以上形式都接受permanent
参数;如果设置为True
会返回一个永久重定向:1
2
3
4def my_view(request):
...
obj = MyModel.objects.get(...)
return redirect(obj, permanent=True)
-
-
reverse()
-
在主路由上添加
namespace
1
2
3
4
5
6
7
8
9
10# urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path("admin/", admin.site.urls),
path("user/", include("user.urls", namespace="suer")),
] -
在子路由上添加
name
1
2
3
4
5
6
7
8
9
10
11
12
13# user/urls.py
from django.urls import path
from user.views import *
# 注意:主路由上添加完namespace后会报错,需要在每个子路由中添加app_name
app_name = "user"
urlpatterns = [
path("login/", login, name="login"),
path("show/", show, name="show"),
] -
使用reverse
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18# user/views.py
from django.shortcuts import render, redirect
from django.urls import reverse
# Create your views here.
def login(request):
if request.method == 'POST':
return redirect(reverse('user:show'))
# 直接用redirect重定向亦可
return redirect('user:show')
return render(request, 'user/login.html')
def show(request):
users = User.objects.all()
return render(request, 'user/show.html', {'users': users})
-