view视图
# 对应脑图
)
# 1. *CBV和FBV视图*
前后端不分离借鉴
# 1.1 FBV
下面是一个返回当前日期和时间作为HTML文档的视图:平常用函数写的就是FBV
from django.http import HttpResponse
import datetime
def current_datetime(request):
now = datetime.datetime.now()
html = "<html><body>It is now %s.</body></html>" % now
return HttpResponse(html)
2
3
4
5
6
7
让我们逐行分析一下上面的代码:
- 首先,从
django.http
模块导入了HttpResponse
类,以及Python的datetime库。 - 接着,我们定义了
current_datetime
视图函数。 - 每个视图函数都接收一个
HttpRequest
对象作为第一位置参数,一般取名为request
,你可以取别的名字,但这不符合潜规则,最好不要那么做。 - 视图函数的名称没有强制规则,但尽量不要和Python及Django内置的各种名称重名,并且尽量精确地反映出它的功能,比如这里的
current_datetime
。 - 该视图返回一个
HttpResponse
对象,其中包含生成的HTML页面。
# 1.2 CBV
用面向对象的方式就是CBV
from django.views import View
class xxx(View):
def dispatch(self, request, *args, **kwargs):
return super().dispatch(request, *args, **kwargs)#其实
def get(self,request):
#专门处理get请求
return response
def post(self,request):
#专门处理post请求
return response
2
3
4
5
6
7
8
9
10
11
12
13
url(r"xx/",xxx.as_view()) # 类名.as_view()执行
# as_view()的流程
1. 项目运行时加载urls.py文件,执行类,as_view()方法
2. as_view()执行后,内部定义了一个view函数,并且返回.
3. 请求到来的时候,执行view函数
1. 实例化类--> self
2. self.request = request
3. 执行self.dispath(request,*args,**kwargs)方法
1. 判断请求方式是否被允许
1. 允许: - 通过反射获取请求方式对应的请求方法--->handler f.html_method_not_allowed -->handler
2. 不允许:- self.http_method_not_allowed -->handler
2. 执行hanlder,返回结果
# http_method_names = ['get'] #只允许提交的请求方法,内部执行View这个函数的时候,就会先访问这个类,这个http_method_names就会覆盖内部的这个方法
def dispatch(self, request, *args, **kwargs):
print("dispatch执行前的操作")
ret = super().dispatch(request, *args, **kwargs)#其实就是执行View里面内部的dispatch方法
print("dispatch执行后的操作")
return ret
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
CBV执行get和post方法前会,先执行dispatch方法
# 2. *FBV和CBV装饰器*
# 2.1 FBV
直接加在函数上就行了
# 2.2 CBV
需要使用一个装饰器,导入包method_decorator
from django.utils.decorators import method_decorator
@method_decorator 是将函数装饰器转换成方法装饰器。
2
# a. 加在方法上
@method_decorator(timer)
def get(self, request): #这样就只能get方法可以用
2
# b. 加在dispatch方法上
@method_decorator(timer) #里面的定义的请求方法都可以用
def dispatch(self, request, *args, **kwargs):
print("dispatch执行前的操作")
ret = super().dispatch(request, *args, **kwargs)#其实就是执行View里面内部的dispatch方法
print("dispatch执行后的操作")
return ret
2
3
4
5
6
# c. 加在类上
@method_decorator(timer,name="get")
@method_decorator(timer,name="post")
@method_decorator(timer,name="dispatch")
class PublishersAdd(View): #加在类上,可以指定对应的方法
2
3
4
# 3. 错误响应
# 4. 异步视图
# 4.1 异步同步视图async
Django3.1开始支持异步视图函数。
编写异步视图,只需要用Python的async def
关键字语法。Django将自动地探测和运行视图在一个异步上下文环境中。
为了让异步视图发挥它的性能优势,你需要启动一个基于ASGI的异步服务器。
在Django中,可以通过async def
语法,将任何函数视图定义为异步视图。
对于类视图,则是将它的__call__()
方法定义为async def
,成为异步视图。
Web服务器可分为WSGI和ASGI两种模式,在不同的模式下,同步和异步视图有性能差别:
- WSGI+同步视图:传统模式
- ASGI+异步视图:性能最佳的异步模式
- WSGI+同步视图+异步视图:传统模式混杂异步,异步视图的性能不能正常发挥
- ASGI+同步视图+异步视图:异步模式混杂传统视图,异步性能最佳
WSGI 服务器下,异步视图将在其自有的一次性事件循环中运行。这意味着你可以放心使用异步特性(例如并发异步 HTTP 请求),但是你不会获得异步堆栈的好处。
ASGI的主要优点则是无需使用 Python 线程就能服务数百个连接。这就允许你使用慢流(slow streaming)、长轮询和其他响应类型。
(附ASGI官方文档地址:https://asgi.readthedocs.io/en/latest/extensions.html)
说明:
如果你的站点中没有同步的中间件,那么你将得到完全的异步请求栈的好处。如果有一个同步中间件,那么Django必须在每个请求中使用一个线程来安全地为它模拟一个同步环境。
中间件可以同时支持同步和异步上下文。Django的一些内置中间件就是这么构建的,但不是所有都这样。换句话说,就是目前你还无法原生得到完全的异步请求栈的性能。
由于ORM对数据库的访问这块依然没有实现异步处理,还是同步的。所以在一个异步视图中,你需要使用Django给你的sync_to_async()
方法将ORM操作包裹起来。例如:
下面是一个异步视图的例子:
import datetime
from django.http import HttpResponse
async def current_datetime(request):
now = datetime.datetime.now()
html = '<html><body>It is now %s.</body></html>' % now
return HttpResponse(html)
async def my_view(request):
await asyncio.sleep(0.5)
return HttpResponse('Welcome to visit https//www.liujiangblog.com for Django course')
2
3
4
5
6
7
8
9
10
11
简要说明:
- 异步功能同时支持WSGI和ASGI模式
- 在WSGI模式下,使用异步功能会有性能损失
- 可以混用异步/同步视图或中间件,Django会自动处理其中的上下文
- 建议主要使用同步模式,在有需求的场景才使用异步功能。
- Django的ORM系统、缓存层和其它的一些需要进行长时间网络/IO调用的代码依然不支持异步访问,在未来的版本中将逐步支持。
- 异步功能不会影响同步代码的执行速度,也不会对已有项目产生明显的影响。
# 5. 请求request和响应response
# 5.1 request
# 常用
常用属性:
request.method 请求方法 GET POST
request.GET URL上携带的参数 ?k1=v1$k2=v2 {}
request.POST post请求提交的数据 {} 编码方法是URLencode
request.path_info 路径信息 不包含IP和端口 也不包含参数 /publisher_list/
request.body 请求体,byte类型 request.POST的数据就是从body里面提取到的(获取的是post请求提交的内容)
request.COOKIES cookies
request.session session类似于字典的对象
request.FILES 上传的文件
request.META 头的信息 小写-->大写 HTTP_开头
不常用属性:
request.scheme() http或https
request.path() 表示请求的路径组件(不含域名)
常用方法:
request.get_full_path() 完整的路径信息 不包含IP和端口 ,包含参数
request.is_ajax() 请求是否是ajax请求
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 更多
HttpRequest对象 (opens new window)
# 5.2 response
# 常用
from django.shortcuts import render, HttpResponse, redirect
HttpResponse("字符串") #返回字符串
render(request,"模板的文件名",{'k1':v1}) #返回一个HTML页面
redirect('地址') #重定向 其实就是给了 Location '地址'和状态码 301 302
from django.http import JsonResponse
def text_json(request):
a = {"a":"b"}
b = ["aa","bb"]
return JsonResponse(b,safe=False) #加safe=False了可以传递列表
2
3
4
5
6
7
8
9
10
11
# 更多
HttpResponse对象 (opens new window)
1