高级视图_类视图

Django类视图

1、在写视图的时候,Django除了使用函数作为视图,也可以使用类作为视图。使用类视图可以使用类的一些特性,比如继承、多态等

2、django视图分为两种:
    ⑴FBV:基于函数的视图
    ⑵CBV:基于类的视图 (Django中自带了几种类视图的定义方式,后面会逐步介绍)
    ⑶前面所学习的所有章节中都是使用函数来编写视图的:通过URL来确定对应的视图函数,使用函数来确定响应内容
    ⑷使用类作为视图,会有很多方便的地方,比如类的继承等,另一方面就是更有利于项目、代码的管理
    
3、一个视图函数(类),简称视图,是一个简单的Python函数(类),它接受Web请求并且返回Web响应
    ⑴响应可以是一张网页的HTML内容,一个重定向,一个404错误,一个XML文档,或者一张图片
    ⑵无论视图本身包含什么逻辑,都要返回响应

    

 

使用函数视图

1、前面章节中都是使用函数来作为视图的,涉及到的例子也是很多,具体的可以看前面的

2、比如:当我们在开发一个注册模块时,浏览器会通过get请求让注册表单弹出来,然后用户输完注册信息后,通过post请求向服务端提交信息
    ⑴这时候我们后端有两个视图函数,一个处理get请求,一个处理post请求。两个视图函数都是不同的名字
    ⑵但是随着开发的进行。当你想要找到注册模块的这两个视图,太麻烦了。如果这两个视图函数能放在一起,归成一个类,作为注册模块的类。这样日后的维护将会方便很多(django的类视图就能实现这个功能了)
    ⑶当然这个例子中通常是将get请求和post请求放到一个视图函数中,然后需要在视图函数中判断当前的请求方式,不同的请求方式对应不同的处理

例1:函数视图
⑴编辑视图
高级视图_类视图

⑵编辑模板
高级视图_类视图

⑶请求方式为GET
高级视图_类视图

⑷请求方式为POST
高级视图_类视图

⑸其他请求方式
高级视图_类视图

 

 

View类视图

1、django.views.generic.base.View是主要的类视图,所有的类视图都是继承自它。如果我们写自己的类视图也可以继承自他,然后再根据当前请求的method,来实现不同的方法。
    ⑴比如这个视图只能使用get的方式来请求,那么就可以在这个类中定义get(self,request,args,**kwargs)方法
    ⑵如果只需要实现post方法,那么就只需要在类中实现post(self,request,args,**kwargs)方法
    ⑶以此类推

2、类视图写完后,还应该在urls.py中进行映射,映射的时候就需要调用View的类方法as_view()来进行转换
    ⑴as_view()是用来分发请求方法的。可以把同一个页面的不同请求方法分发给不同的视图来执行

3、类视图提供了一种使用Python对象实现视图的方法。类视图不会替代函数视图, 与函数视图相比,它们有一定的差异和优势:
    ⑴采用单独的函数来处理特定 HTTP请求(GET,POST等)代替函数视图的条件分支
    ⑵可以使用面向对象的技术,如 mixins(多重继承)将代码重新定义为可重用的组件

4、view类视图的核心思想在于使用不同的类实例方法响应不同的HTTP请求方法(同一个URL),而不是在单个视图函数中使用条件分支代码

例2:请求方式为GET的类视图
⑴编辑视图
高级视图_类视图

⑵编辑URL映射
高级视图_类视图

⑶访问
高级视图_类视图

注:
1、在编写类视图时,需要注意:
    ⑴导入View模块
    ⑵自己编写的视图类继承View
    ⑶self是Python类方法中的第一个参数,request是Django视图的第一个参数(这两个是固定的)。args表示所有的位置参数、kwargs表示所有的关键字参数(类视图方法中不需要参数时,可以不写这两个形参,只需要self和request就好了)

2、在编写URL映射时一定要调用as_views()方法

3、可以看到,在编写URL映射时,并没有准确的定位到我们的类视图中的某个方法,而只是定位到了类名后,就调用了as_views()方法
    ⑴这就是views类视图的好处之一:views类视图会自动根据当前的请求方式去执行对应的方法(请求名与方法名一致)

例2_1:请求方式为多种
⑴编辑视图
高级视图_类视图

⑵请求方式为GET访问
高级视图_类视图

⑶请求方式为POST访问
高级视图_类视图

注:
1、这个例子中视图类中定义了两个方法get()和post(),这两个方法分别对应该URL的GET方式请求和POST方式请求
    ⑴首先这个URL支持两个请求方式(GET请求和POST请求):都是针对同一个URL的不同请求方式,因此可以将两种不同的请求方式定义在同一个视图类的不同方法中(这种就不需要再视图中判断当前的请求方式了)
    ⑵可以看到:同一个视图类中定义了不同的方法时,Django会自动的根据当前的请求方式来执行不同的方法(方法名是请求方式的小写形式)

2、除了get方法,View还支持以下方法'get','post','put','patch','delete','head','options','trace'
    ⑴只是说这里只是介绍了表常用的GET和POST请求方式

3、定义视图类跟视图函数是差不多的。类视图其实就是根据请求方式来将处理过程定义在对应的类方法中(请求名与方法名一致)
    ⑴类视图中也支持定义查询字符串参数和URL参数

例3:通过URL传递参数
⑴编辑视图
高级视图_类视图

⑵访问
高级视图_类视图


例3_1:查询字符串参数
⑴编辑视图
高级视图_类视图

注:
1、可以看到其实视图类与视图函数时差不多的
    ⑴个人感觉:视图类主要就是用于一个URL有多种请求方式时,根据请求方式来编写不同的处理方法(请求名与方法名一致)

2、如果用户访问了View中没有定义的方法。比如你的类视图只支持get方法,而出现了post方法,那么就会把这个请求转发给http_method_not_allowed(request,*args,**kwargs)
    ⑴http_method_not_allowed()方法就会返回一个405错误
    

例4:定义一个请求方式为GET的方法
⑴编辑视图
高级视图_类视图

⑵访问
高级视图_类视图

注:
我们也可以自己定义一个http_method_not_allowed()方法来指定请求方式错误时返回的内容

例4_1:
⑴编辑视图
高级视图_类视图

⑵访问
高级视图_类视图

注:
其实不管是get请求还是post请求,都会走dispatch(request,*args,**kwargs)方法,所以如果实现这个方法,将能够对所有请求都处理到

例5:
⑴查看源码
高级视图_类视图

 

 

TemplateView类视图

1、django.views.generic.base.TemplateView这个类视图是专门用来返回模版的。在这个类中,有两个属性是经常需要用到的
    ⑴template_name:这个属性是用来存储模版的路径,TemplateView会自动的渲染这个变量指向的模版
    ⑵get_context_data:这个方法是用来返回上下文数据的,也就是在给模版传的参数的
    
2、通常这个TemplateView类是用来渲染一个完全不需要传递参数的HTML模板的
    ⑴即:如果一个模板不需要通过视图函数(类)来向其传递参数(模板中的内容完全是写死了的),那么就可以直接使用TemplateView类来进行渲染,都不需要定义其的视图函数了

3、需求:在一个网站中,有一些页面不需要我们从数据库中提取数据到前端页面中,例如网址中的“关于我们” 这个页面一般都是在html中写死的数据,不需要进行改动
    ⑴这个时候我们就可以直接在urls.py中直接渲染html文件(使用TemplateView类),而不用视图函数或者视图类来进行渲染

例6:
⑴编辑模板
高级视图_类视图

⑵编辑URL映射
高级视图_类视图

⑶访问
高级视图_类视图

注:
1、可以看出:如果一个模板不需要传递任何的参数,那么就可以使用TemplateView类在URL映射中直接渲染这个模板(视图函数都不需要定义了)

2、当然,虽然TemplateView类经常用于渲染不需要传递参数的模板,但是实际上还是可以给TemplateView类所渲染的模板传递参数的,只是写法就不一样了

3、当想使用这个TemplateView进行渲染模板,又想传递少许参数,这个时候我们就可以定义一个类,继承自TemplateView

例6_1:
⑴编辑视图
高级视图_类视图

⑵编辑URL映射
高级视图_类视图

⑶编辑模板
高级视图_类视图

⑷访问
高级视图_类视图

 

 

拓展

类视图补充

1、类视图:Django中自带了多种类视图,各种类视图有不同的功能(目前介绍了两种类视图)
    ⑴View类视图:一个视图对应的URL提供了多种不同HTTP请求方式的支持时,便需要在一个视图函数中根据不同的请求方式来编写不同的业务逻辑。这样就显得根式麻烦。因此可以使用View类视图来将视图对应的不同请求方式以类中的不同方法来分别定义(就不需要判断当前的请求方式了)
    ⑵TemplateView类视图:如果一个模板不需要通过视图函数(类)来向其传递参数,那么就可以直接使用TemplateView类来进行渲染(也可以向TemplateView渲染的模板传递参数)

2、需要说明的就是:
    ⑴类视图不是说将很多视图函数(具有相同点的视图函数)定义在某一个类中,而是在某些特定场景下可以使用Django自带的类视图来简化我们视图函数的编写
    ⑵比如View类视图:一个URL有多种请求方式,将不同的请求方式的处理过程定义在同一个类的不同方法中

3、还有种情况就是:随着项目的发展,代码会越来越多,如果都是只是使用函数来作为视图的话,那就会产生很多函数。当想找某个视图函数时就会显得很麻烦
    ⑴因此就可以将一些具有相同地方的函数放到一个类中,使用类来作为视图,这样更便于管理
    ⑵其实就是跟Python类的作用差不多:都是将一些具有相同地方的函数放到一个类中,这样就可以使用类的特性,也有利于代码的管理
    ⑶但是这种情况并不是类视图,这个的意思跟类视图完全是两个东西

例7:
⑴编辑视图
高级视图_类视图

⑵编辑首页模板
高级视图_类视图

⑶编辑添加图书模板
高级视图_类视图

注:
1、按理说Python类方法的第一个参数应该是self的,Django视图函数的第一个参数是request但是我在写的时候先写的是"index(self,request)",但是报错了,提示我少了一个必须参数request
    ⑴所以我感觉应该是没识别到方法中的request,所以我就将第一个参数改成了request,结果还真的可以
    ⑵Python类方法的第一个参数必须是self,但是不需要一定的self也可以是其他的,只是代表的意思是一样的,所以这里request既是Python类方法的第一个参数必须是self,也是jango视图函数的第一个参数是request

2、这种写法是我自己想的,不知道是否正确,不过写出来是可以正常运行的
    ⑴在进行URL映射时,需要定位到具体的类方法:"模块名.类名.方法名",这样才能Django才能知道哪个URL调用的是哪个类方法
3、注意:这种场景的话不是类视图,一定要与前面介绍的类视图区分来
    ⑴类视图:在某些特定的场景下可以选择使用Django自带的类视图来处理视图函数。比如这里的View类视图和TemplateView类视图都是针对某一特定场景的
    ⑵这个例子:是将同一个模块中的视图函数定义在同一个类中,针对的是同一个业务模块、不同的URL。不需要继承于Views模块等

4、开始学django的时候,只知道基于函数的视图,这对于初学者来说是友好的。后来写的东西复杂的时候,特别是HTTP请求不止是一开始单一的GET时,我更偏向于继承django.views.generic.View,简单覆盖方法就可以处理请求了。所以在写代码的时候要根据实际场景来决定使用视图函数还是类视图等