视图基础
Django的视图主要有2种,分别是视图函数和视图类,现在我们先从视图函数(FBV)进行入手,后面再学习视图类(CBV)
- Function BaseView:函数基本视图
- Class BaseView:类基本视图
一、函数视图
Django中所有的函数视图必须编写在子应用的views.py文件中
from django.http.response import HttpResponse
def 函数视图名称(request):
# 代码
return HttpResponse("返回内容")
函数视图名称,同一个模块下不能重复,同时采用变量命名规则
参数request解释:
Django经过路由调用视图时,会默认传递一个request对象,request对象是http协议的一个代理对象,我们只需要调用request对象的方法就可以拿到我们需要的内容了
二、请求
2.1 限制http请求
web项目运行在http协议下,默认肯定也支持用户通过不同的http请求发送数据
常用的http请求:
- POST:添加/上传
- GET:获取/下载
- PUT/PATCH:修改,其中PUT表示修改整体数据,而PATCH表示修改部分数据
- DELETE:删除/废弃
Django支持让客户端只能通过指定的HTTP请求方式来访问到项目的视图
在子应用home下的views.py下编写如下代码:
# 限制http请求访问视图
def drop(request):
return HttpResponse(f'删除视图,该方法的请求方式是:{request.method}') # request.method 获取http请求的方法
在主应用下的urls.py中建立映射关系:
path('drop/', views.drop),
通过浏览器访问http://localhost:8000/drop/
,发现此次访问HTTP的请求方式是GET请求
修改视图函数drop:
from django.views.decorators.http import require_http_methods
# 限制http请求访问视图
@require_http_methods(['delete'])
def drop(request):
return HttpResponse(f'删除视图,该方法的请求方式是:{request.method}') # request.method 获取http请求的方法
再次通过浏览器访问http://localhost:8000/drop/
,发现访问失败,浏览器报错405 Method Not Allowed
,那么此时只能通过DETELETE请求来访问drop视图函数。
找到主应用下的settings文件,修改中间件的配置,将'django.middleware.csrf.CsrfViewMiddleware'
这一行删除来关闭Csrf。
通过Postman发送DELETE请求至http://localhost:8000/drop/
,请求通过
2.2 设置路由绑定视图
目前这种路由视图映射关系全部写在了主应用下的urls.py中,当然这么做是不灵活的,如果当项目庞大了之后,上千个路由映射就要写条映射关系,这样不仅不够灵活,也不够优雅。
在创建项目时,主应用下的urls.py中有这样一段注释:
"""djdemo URL Configuration
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/4.0/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path('', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
官方提供了三种路由视图映射关系的绑定:
- Function views:函数视图
- Class-based views:类视图
- Including another URLconf:包含其他的URL配置
这里我们就根据官方提供的第三种方式Including another URLconf来修改当前冗余的urls配置:
-
根据文档
Import the include() function: from django.urls import include, path
,首先导入include()函数from django.urls import path, include
-
添加映射关系
Add a URL to urlpatterns: path('blog/', include('blog.urls'))
path('home/', include('home.urls')),
-
将之前子应用home的映射关系迁移到自己应用下
- 在home应用下新建python文件
urls.py
- 将主应用中的urls.py映射关系迁移到home中的urls.py中
- 在home应用下新建python文件
完成后主应用及子应用下的代码:
主应用django
下的urls.py:
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('home/', include('home.urls')),
]
path(‘home/’, include(‘home.urls’)) 的说明:
path(‘子路由所有路由共同的前缀’, include(‘子应用的目录名.urls’)) 的说明:
子应用home
下的urls.py:
from django.urls import path
from home import views
urlpatterns = [
path('hello/', views.index),
path('drop/', views.drop),
]
之后访问http://localhost:8000/home/hello/
进行测试
2.3 视图接收http请求
在http请求和响应过程中,用户往往会在请求过程中发送请求信息给服务端
-
查询字符串[Query String]
-
所谓的查询字符串就是url地址上面?号后面的数据,例如:
http://127.0.0.1:8000/index?name=Abo&pwd=123456
上面的name=Abo&pwd=123456就是查询字符串
在Django中可以通过request.GET来获取,注意:GET不是http请求,也就是说,只要地址上有查询字符串,都可以获取
-
-
请求体数据
-
请求头报文信息
-
上传文件
2.3.1 request对象
request对象是当用户请求Django时,由wsgi.py中的application web应用对象,会自动帮我们解析http请求的文本内容,并把对应的内容,赋值给request对象的。request对象是from django.core.handlers.wsgi.WSGIRequest
请求处理类的实例对象,WSGIRequest继承自django.http.request.HttpRequest
,日常开发中使用到的大部分属性功能其实都是HttpRequest提供的
导入HttpRequest的方式:from django.core.handlers.wsgi import WSGIRequest
2.4 获取查询字符串的参数
2.4.1 准备工作
在子应用home中新增视图函数index2及建立路由映射关系
-
视图函数:
def index2(request): """ 查看request对象提供的常用属性 """ print(request) print(request.__dir__()) # 列出调用者的类目录(即调用者的所有属性及方法) print(request.method) # 获取本次客户端的http请求方法 print(request.GET) # 获取查询字符串参数(即url?号后面拼接的参数),这里的GET是一个方法,被@cached_property装饰器所装饰,是django内部用于优化性能的一种方式 print(f"name={request.GET['name']}") # 获取请求字符串中的name参数,直接通过[]的方式取值如果没有这个key会报错 print(f"pwd={request.GET['pwd']}") # 获取请求字符串中的pwd参数,直接通过[]的方式取值如果没有这个key会报错 # url: http://localhost:8000/home/index2/?name=Abo&pwd=123456&like=music&like=book print(f"like={request.GET.get('like', None)}") # 获取请求字符串中的like参数,通过get()方法取值没有不会报错,也可以通过get()方法的第二个参数指定没有参数时的默认值 print(f"like={request.GET.getlist('like', None)}") # 获取请求字符串中的like参数列表 return HttpResponse('ok')
-
路由映射
path('index2/', views.index2),
2.4.2 获取查询字符串的方法介绍
- request.method:获取本次客户端的http请求方法
- request.GET:获取查询字符串参数(即url?号后面拼接的参数),这里的GET是一个方法,被@cached_property装饰器所装饰,是django内部用于优化性能的一种方式
- request.GET[‘key’]:获取请求字符串中的key参数,直接通过[]的方式取值如果没有这个key会报错
- request.GET.get(‘key’, None):获取请求字符串中的key参数,通过get()方法取值没有不会报错,也可以通过get()方法的第二个参数指定没有参数时的默认值
- like={request.GET.getlist(‘key’, None):获取请求字符串中的key参数列表
2.4.3 QueryDict参数集
视图函数打印request.GET
,然后浏览器访问http://localhost:8000/home/index2/?name=Abo&pwd=123456
,执行结果如下:
<QueryDict: {'name': ['Abo'], 'pwd': ['123456'], 'like': ['music', 'book']}>
QueryDict说明:
- QueryDict是参数集对象,类的位置:django.http.QueryDict
- QueryDict对象继承自MultiValueDict对象,而MultiValueDict对象又继承自dict
- 完全可以当做使用字典的方式来操作QueryDict
2.5 获取请求体数据
2.5.1 准备工作
在子应用home中新增视图函数index2及建立路由映射关系
-
视图函数
def index3(request): """ 获取请求体数据 """ # request相关方法代码 return HttpResponse('OK')
-
路由映射关系
path('index3/', views.index3),
-
由于只有PUT/DELETE/PATCH请求方式拥有请求体,所以提前准备好Postman
2.5.2 获取请求体数据的方法介绍
- request.POST:接收客户端html表单数据(postman设置了发送请求通过
form-data
发送),这种方法不能接收上传文件 - request.body:接收Json格式数据,其实是拿到原生的请求体数据,从http协议中提取出来没有经过任何处理的原生数据
- 原生请求体样式我们是无法直接使用的,如果是知道是json样式,可以采用下面的这种方式处理:
- import json
- json.loads(request.body)
- 通过上述这种方式得确保是json格式,其他样式解析出来的数据依旧不能使用,甚至会报错
- 原生请求体样式我们是无法直接使用的,如果是知道是json样式,可以采用下面的这种方式处理:
2.6 获取请求头数据
2.6.1 准备工作
def index4(request):
""" 获取请求头数据 """
return HttpResponse('OK')
path('index4/', views.index4),
2.6.2 获取请求头数据的方法介绍
- request.META:获取原生请求头数据
2.7 获取上传文件
2.7.1 获取上传文件的方法介绍
- request.FILES:接收所有的上传文件
- request.FILES.get(key):接收单个文件上传处理对象,获取到的参数类型是
InMemoryUploadFile
三、响应Response
3.1 视图响应数据
django和大多数的web框架一样,针对http的响应,提供了两种不同的响应方式:
- 响应内容,就是直接返回数据给客户端
- 响应html内容(一般用于web前后端不分离的项目)
- 响应json内容(一般用于开发web前后端分离的项目的api接口开发)
- 响应页面,就是通过返回页面跳转的信息给浏览器,让浏览器自己进行页面跳转
3.1.1 返回HTML数据
HttpResponse可以直接返回html内容
def index5(request):
""" 响应html内容 """
return HttpResponse(content='<H1>OK</H1>', status=201)
3.1.2 返回Json
方式一:通过导入json包响应
import json
def index6(request):
""" 响应json内容 """
data = {
'name': 'Abo',
'age': 22,
'sex': '男'
}
res = json.dumps(data)
return HttpResponse(content=res, content_type='application/json')
返回json数据,可以通过HttpRequestd的属性:content_type
来指定数据的返回格式
- content_type的默认值是text/html
- 如果指定返回格式为json,可以指定为:
content_type='application/json'
方式二:通过导入JsonResponse响应
from django.http.response import JsonResponse
def index7(request):
""" 响应json内容 """
data = {
'name': 'Abo',
'age': 22,
'sex': '男'
}
return JsonResponse(data=data)
说明:
JsonResponse
继承自HttpResponse,是专门用于响应Json数据的类- 使用JsonResponse响应时不再是使用content指定响应的数据,而是通过
data
来指定响应的数据 - 使用JsonResponse响应时不再需要指定content_type了,其内部已经指定了content_type='application/json‘
3.1.3 返回图片信息
def index7(request):
""" 响应纯图片信息内容 """
content = open('release.png', 'rb').read()
return JsonResponse(content, content_type='image/jpeg')
3.1.4 提供下载支持
def index7(request):
""" 提供下载支持(以zip格式演示,可以是其他格式) """
with open('./basic-2.2.1.zip', 'rb') as f:
content = f.read()
return JsonResponse(content, content_type='application/x-zip-compressed')
3.1.5 自定义响应头
def index7(request):
""" 自定义响应头 """
response = HttpResponse('ok')
reponse['company'] = 'AboCompany' # 给响应对象设置自定义响应头
return response