一个视图函数(类),简称视图,是一个简单的Python 函数(类),它接受Web请求并且返回Web响应。
响应可以是一张网页的HTML内容,一个重定向,一个404错误,一个XML文档,或者一张图片。
无论视图本身包含什么逻辑,都要返回响应。代码写在哪里也无所谓,只要它在你当前项目目录下面。除此之外没有更多的要求了——可以说“没有什么神奇的地方”。为了将代码放在某处,大家约定成俗将视图放置在项目(project)或应用程序(app)目录中的名为views.py的文件中。
FBV和CBV
FBV:基于函数的视图;
CBV:基于类的视图;
url(r'^add_class/$', views.view), # FBV
url(r'^add_class/$', views.AddClass.as_view()) # CBV
FBV 添加班级
def add_class(request):
if request.method == "POST":
class_name = request.POST.get("class_name")
models.Classes.objects.create(name=class_name)
return redirect("/class_list/")
return render(request, "add_class.html")
CBV添加班级
CBV 需要继承view类
from django.views import View
class AddClass(View):
def get(self, request):
return render(request, "add_class.html")
def post(self, request):
class_name = request.POST.get("class_name")
models.Classes.objects.create(name=class_name)
return redirect("/class_list/")
CBV源码
函数名加括号执行优先级最高
项目已启动就会执行as_view方法 查看源码返回了一个闭包函数名view
AddClass.as_view() 运行的结果就是view; 所以 views.AddClass.as_view()=views.view
所以 CBV 路由匹配的本质,就是 FBV
接下来,我们分析一下,当路由匹配成功时,需要执行的这个view函数的源码
@classonlymethod
def as_view(cls, **initkwargs):
... ... # 源码省略
def view(request, *args, **kwargs):
self = cls(**initkwargs) -----> '实例化生成一个对象'
if hasattr(self, 'get') and not hasattr(self, 'head'):
self.head = self.get ----> '给生成的对象添加 head 属性'
self.request = request ----> '给生成的对象添加 request 属性'
self.args = args ----> '给生成的对象添加 args 属性'
self.kwargs = kwargs ----> '给生成的对象添加 args 属性'
return self.dispatch(request, *args, **kwargs)
... ... # 源码省略
return view
最为重要的部分就是 return self.dispatch(request, *args, **kwargs)
由于,对象 和 产生对象的AddClass类中都没有 dispatch函数,所有需要到AddClass的父类View中去找
判断当前请求的方法是否符合 8 个 默认的请求方法
getattr( 对象, 请求的方法(字符串), 拿不到请求方法的报错信息) --> 拿到了AddClass我们自定义类的 get方法
最后一步就是 执行了 我们自定义的 get方法