FBV
FBV就是urlpatterns中一个路径对应一个函数
urls:
urlpatterns = [
url(r'^index_fbv/', views.index_fbv),
]
视图中:
def index_fbv(request):
return render(request, 'index.html')
CBV
cbv就是在url中一个路径对应一个类
urls:
urlpatterns = [
url(r'^index_fbv/', views.index_fbv),
url(r'^index_cbv/', views.IndexView.as_view())
]
视图中:
class IndexView(View):
# 以get形式访问会执行get函数,一般情况下获取数据
def get(self, *args, **kwargs):
return HttpResponse('666')
# 以post形式访问的话会执行post函数,一般情况下发送数据
def post(self, *args, **kwargs):
return HttpResponse('999')
注意FBV与CBV在urls中的写法不同以及在视图中定义方式不同,但是本质上都是通过dispatch这个函数反射执行:
- CBV定义类的时候必须要继承view
- CBV在写url的时候必须要加as_view
下面整理下CBV是怎么样重新定义dispatch函数的
如果想要在执行get或post方法前执行其他步骤,可以重写dispatch
class IndexView(View):
# 重写父类的dispatch方法,如果不重写,他会执行父类的dispatch方法,
def dispatch(self, request, *args, **kwargs):
print('request---------before')
res = super(IndexView, self).dispatch(request, *args, **kwargs)
print('request---------after')
return res
# 以get形式访问会执行get函数
def get(self, *args, **kwargs):
print('------------request---------')
return HttpResponse('666')
# 以post形式访问的话会执行post函数
def post(self, *args, **kwargs):
return HttpResponse('999')
打印结果:
request---------before
------------request---------
request---------after
下面我们根据上面的写法添加用户登录验证
from django.shortcuts import render, HttpResponse, redirect
from django.views import View
class LoginView(View):
def get(self, request):
return render(request, 'login.html')
def post(self, request):
user = request.POST.get('user')
pwd = request.POST.get('pwd')
if user == 'rdw' and pwd == '666':
request.session['user_info'] = 'rdw'
return redirect('/index/')
else:
return render(request, 'login.html')
class IndexView(View):
# 重写父类的dispatch方法,如果不重写,他会执行父类的dispatch方法,
def dispatch(self, request, *args, **kwargs):
if not request.session.get('user_info'):
return redirect('/login/')
res = super(IndexView, self).dispatch(request, *args, **kwargs)
return res
# 以get形式访问会执行get函数
def get(self, request, *args, **kwargs):
return render(request, 'index.html')
# 以post形式访问的话会执行post函数
def post(self, *args, **kwargs):
return HttpResponse('999')
给视图类添加装饰器
如果有多个程序需要用户登录验证的话会造成代码冗余,可以使用继承很好的解决这个问题,但是还有更好的方法,那就是基于装饰器实现登录验证
定义装饰器
def login_test(func):
def inner(request, *args, **kwargs):
if not request.session.get('user_info'):
return redirect('/login/')
return func(*args, **kwargs)
return inner
直接添加在dispatch里面,这样每个函数都会执行
from django.utils.decorators import method_decorator
@method_decorator(login_test)
def dispatch(self, request, *args, **kwargs):
res = super(IndexView, self).dispatch(request, *args, **kwargs)
return res
添加在每一个函数中
from django.utils.decorators import method_decorator
@method_decorator(login_test)
def get(self, request, *args, **kwargs):
return render(request, 'index.html')
直接添加在类上,后面的name表示只给get添加装饰器
from django.utils.decorators import method_decorator
@method_decorator(login_test, name='get')
class IndexView(View):
注意:
添加装饰器前必须导入from django.utils.decorators import method_decorator
添加装饰器的格式必须为@method_decorator(),括号里面为装饰器的函数名
给类添加是必须声明name
注意csrf-token装饰器的特殊性,它只能加在dispatch上面