视图
视图
django中的逻辑处理主要是在视图(views
)中完成,而视图分为两类:函数视图(FBV
)和类视图(CBV
)。
介绍
一个视图函数(类),简称视图,是一个简单的Python 函数(类),它接受Web请求并且返回Web响应。
响应可以是一张网页的HTML内容,一个重定向,一个404错误,一个XML文档,或者一张图片。
放置在项目(project)或应用程序(app)目录中的名为views.py的文件中。
下面是一个以 HTML 文档的形式返回当前日期和时间的视图:
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)
让我们来逐行解释下上面的代码:
首先,我们从 django.http
模块导入了HttpResponse
类,以及Python的datetime
库。
接着,我们定义了current_datetime
函数。它就是视图函数。每个视图函数都使用HttpRequest
对象作为第一个参数,并且通常称之为request
。
注意,视图函数的名称并不重要;不需要用一个统一的命名方式来命名,以便让Django识别它。
我们将其命名为current_datetime
,是因为这个名称能够比较准确地反映出它实现的功能。
这个视图会返回一个HttpResponse
对象,其中包含生成的响应。
Django使用请求和响应对象来通过系统传递状态。
当浏览器向服务端请求一个页面时,Django创建一个HttpRequest
对象,该对象包含关于请求的元数据。然后,Django加载相应的视图,将这个HttpRequest
对象作为第一个参数传递给视图函数。
每个视图负责返回一个HttpResponse
对象。
FBV
基本用法
- function based view 基于函数的视图
from django.shortcuts import HttpResponse
import datetime
def mul(request):
now = datetime.datetime.now()
return HttpResponse(now)
- 路由映射
from django.conf.urls import path
from app01 import views
urlpatterns = [
upathrl(r'mul/', views.mul),
]
装饰器
FBV 本身就是一个函数,所以和给普通的函数加装饰器无差:
from django.shortcuts import HttpResponse
import time
def wrapper(func):
def inner(*args, **kwargs):
start_time = time.time()
ret = func(*args, **kwargs)
end_time = time.time()
print("used:", end_time-start_time)
return ret
return inner
# FBV版添加装饰器
@wrapper
def add_class(request):
now = datetime.datetime.now()
return HttpResponse(now)
扩充
如果客户端直接向服务器提交post请求,没有携带csrf_token参数,就会出现403,禁止提交。
如果想要绕过csrf验证,有两种选择,一种就是,直接关闭中间件;另一种,就是在视图中,使用csrf装饰器跳过验证。
from django.views.decorators.csrf import csrf_exempt
from django.shortcuts import HttpResponse
@csrf_exempt
def test(request):
name = request.POST.get("name")
return HttpResponse(name)
CBV
基本用法
- class based view 基于类的视图
from django.views import View
from django.shortcuts import HttpResponse
# 处理不同请求方式的逻辑清晰明了
class AddPublisher(View):
def get(self,request):
"""处理get请求"""
return HttpResponse("GET 请求")
def post(self,request):
"""处理post请求"""
return HttpResponse("POST 请求")
- 路由映射
#urls.py 文件
from django.conf.urls import path
from app01 import views
urlpatterns = [
path(r'add_publisher/', views.AddPublisher.as_view()),
] # 固定写法注意.as_view()是要加括号的
执行流程
CBV 如何获取页面请求类型, 并响应的
项目启动,执行
AddPublisher.as_view()
——> viewpath('add_publisher/',views.AddPublisher.as_view())
请求到来时执行
view
函数:实例化
AddPublisher
——》 selfself.request = reqeust
执行
self.dispatch(request,*args,**kwargs)
判断请求方式是否被允许
http_method_names = []
- 允许:通过反射获取到当前请求方式对应的方法 ——> handler
- 不允许:
self.http_method_not_allowed
——> handler
执行
handler(request,*args,**kwargs)
——> 返回响应
装饰器
- 类中的方法与独立函数不完全相同,因此不能直接将函数装饰器应用于类中的方法 ,我们需要先将其转换为方法装饰器。
- Django 中提供了
method_decorator
装饰器用于将函数装饰器转换为方法装饰器。
装饰器加在类方法上
import time
from django.views import View
from django.utils.decorators import method_decorator #导入method_decorator装饰器
def timer(func):
def inner(request, *args, **kwargs):
start = time.time()
ret = func(request, *args, **kwargs)
print("函数执行的时间是{}".format(time.time() - start))
return ret
return inner
class AddClass(View):
@method_decorator(timer) # 将函数装饰器转换为方法装饰器
def get(self,request):
"""处理get请求"""
return HttpResponse("GET 请求")
def post(self,request):
"""处理post请求"""
return HttpResponse("POST 请求")
dispatch() 加装饰器
使用CBV时要注意,请求过来后会先执行dispatch()
这个方法,如果需要对该视图类的所有请求方法做批量处理,就可以在dispatch()
方法上加装饰器,在所有的请求方法中都生效
import time
from django.views import View
from django.utils.decorators import method_decorator #导入方法装饰器
def timer(func):
def inner(request, *args, **kwargs):
start = time.time()
ret = func(request, *args, **kwargs)
print("函数执行的时间是{}".format(time.time() - start))
return ret
return inner
class Login(View):
@method_decorator(timer) #相当于给get,post请求都加上了装饰器
def dispatch(self, request, *args, **kwargs):
obj = super(Login,self).dispatch(request, *args, **kwargs)
return obj
def get(self,request):
"""处理get请求"""
return HttpResponse("GET 请求")
def post(self,request):
"""处理post请求"""
return HttpResponse("POST 请求")
装饰器加在类上
import time
from django.views import View
from django.utils.decorators import method_decorator
def timer(func):
def inner(request, *args, **kwargs):
start = time.time()
ret = func(request, *args, **kwargs)
print("函数执行的时间是{}".format(time.time() - start))
return ret
return inner
@method_decorator(timer,name = 'get') # 相当于给get请求,加上了装饰器
@method_decorator(timer,name = 'post') # 相当于给post请求,加上了装饰器
class Login(View):
def get(self,request):
"""处理get请求"""
return HttpResponse("GET 请求")
def post(self,request):
"""处理post请求"""
return HttpResponse("POST 请求")