Python Django CBV下的通用视图函数
ListView
TemplateView
DetailView
之前的代码实例基本上都是基于FBV的模式来撰写的,好处么,当然就是简单粗暴。。正如:
def index(request):
return HttpResponse('hello world')
上面的写法,基本接触不到视图函数里面的通用视图。只是在介绍CBV的时候稍微介绍了下引用,大概用法。
导入
之前的导入一直用的是
from django.views import View
这里从view下钻一下会发现:
from django.views.generic.base import View __all__ = ['View']
对头、view视图函数基本都来自于generic里面,此篇blog具体讲述的内容也是generic内部的几个通用视图:ListView、DetailView、TemplateView。
View
基础类视图:
from django.http import HttpResponse
from django.views import View class MyView(View):
def get(self, request):
return HttpResponse('ok')
urlpatterns = [
path('index/',views.MyView.as_view(), name='index'),
]
as_view()
方法会返回一个函数来处理请求和响应,还可以将类视图中定义的属性作为该方法参数,覆盖类视图中的属性值。
基本视图
基本视图包括三类:View、TemplateView和RedirectView。用户可继承基本类视图来定义视图,所有的通用视图也都继承与这三类基本视图实现,因此相比于通用视图,基本视图提供的功能较少。
View
View是所有类视图的父类,可以直接从from django.views中导入,如:
from django.views import View class MyView(View): def get(self,request):
pass
http请求的方法
http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
as_view():该方法是一个类方法,被@classonlymethod
修饰,是http请求和响应的入口,用于url配置。在Http请求和响应的过程中,会将request对象和其他参数作为参数传入该方法,内部调用dispatch()
方法后返回一个Response对象。
TemplateView
继承结构:
class TemplateView(TemplateResponseMixin, ContextMixin, View):
TemplateView视图通过给定的模板进行渲染。
实例
class StudentDetailTemplate(TemplateView): # 继承TemplateView
template_name = 'student_template.html' # 模版名称 def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs) # 继承父类里面的get_context_data,返回上下文数据
context['name'] = 'dandy' # 添加新的数据
context['data'] = {
'age': 18, # 添加新的字典
'flag': 'aaa'
}
context['data1'] = models.Student.objects.all() # 添加新的queryset
return context # 返回更新过的上下文文数据
url:
path('templateview/', views.StudentDetailTemplate.as_view(), name='student_template'),
其他为涉及到的属性或方法:
get_template_names()
除了使用template_name
指定模板文件,也可通过该方法指定模板文件:
def get_template_names(self):
return "student_template.html"
extra_content
除了在get_context_data()
中添加上下文信息外,也可以在url配置时在as_view()
方法中指定extra_context
属性来添加上下文信息,如:
path('templateview/', views.StudentDetailTemplate.as_view(extra_context={"extra": "。。。。"}), name='student_template'),
CBV正常是需要在下面定义一个get或之类的方法,用来匹配method,但是此处是不需要的,因为查看TemplateView内部时会发现:
class TemplateView(TemplateResponseMixin, ContextMixin, View):
"""
Render a template. Pass keyword arguments from the URLconf to the context.
"""
def get(self, request, *args, **kwargs):
context = self.get_context_data(**kwargs)
return self.render_to_response(context)
内部已经写好了这个get方法,一方面TemplateView的基础需求其实就是返回模版给浏览器的。当然了,因为继承了TemplateView,这里还是可以重写这个get方法,进行自定义数据。
def get(self, request, *args, **kwargs):
context = self.get_context_data(**kwargs)
context['end'] = 'ending'
new_data ={
'a': 'b'
}
context.update(new_data)
return self.render_to_response(context)
RedirectView
用来进行跳转, 默认是永久重定向(301),可以直接在urls.py中使用,非常方便:
path('', views.IndexPage.as_view(), name='baidu'),
class ArticleCounterRedirectView(RedirectView): url = ' # 要跳转的网址,
# url 可以不给,用 pattern_name 和 get_redirect_url() 函数 来解析到要跳转的网址 permanent = False #是否为永久重定向, 默认为 False
query_string = True # 是否传递GET的参数到跳转网址,True时会传递,默认为 False
pattern_name = 'article-detail' # 用来跳转的 URL, 看下面的 get_redirect_url() 函数 # 如果url没有设定,此函数就会尝试用pattern_name和从网址中捕捉的参数来获取对应网址
# 即 reverse(pattern_name, args) 得到相应的网址,
def get_redirect_url(self, *args, **kwargs):
article = get_object_or_404(Article, pk=kwargs['pk'])
article.update_counter() # 更新文章点击数,在models.py中实现
return super(ArticleCounterRedirectView, self).get_redirect_url(*args, **kwargs)
RedirectView源码:
class RedirectView(View):
"""Provide a redirect on any GET request."""
permanent = False
url = None
pattern_name = None
query_string = False def get_redirect_url(self, *args, **kwargs):
"""
Return the URL redirect to. Keyword arguments from the URL pattern
match generating the redirect request are provided as kwargs to this
method.
"""
if self.url:
url = self.url % kwargs
elif self.pattern_name:
url = reverse(self.pattern_name, args=args, kwargs=kwargs)
else:
return None args = self.request.META.get('QUERY_STRING', '')
if args and self.query_string:
url = "%s?%s" % (url, args)
return url
def get(self, request, *args, **kwargs):
url = self.get_redirect_url(*args, **kwargs)
if url:
if self.permanent:
return HttpResponsePermanentRedirect(url)
else:
return HttpResponseRedirect(url)
else:
logger.warning(
'Gone: %s', request.path,
extra={'status_code': 410, 'request': request}
)
return HttpResponseGone() def head(self, request, *args, **kwargs):
return self.get(request, *args, **kwargs) def post(self, request, *args, **kwargs):
return self.get(request, *args, **kwargs) def options(self, request, *args, **kwargs):
return self.get(request, *args, **kwargs) def delete(self, request, *args, **kwargs):
return self.get(request, *args, **kwargs) def put(self, request, *args, **kwargs):
return self.get(request, *args, **kwargs) def patch(self, request, *args, **kwargs):
return self.get(request, *args, **kwargs)
看完应该就会一目了然。
path('', RedirectView.as_view(pattern_name='backend:index')),
通用显示视图
ListView
继承关系:
ListView,用于显示一个对象列表的视图,包含一个属性值object_list
,表示对象的列表。因此在模板文件中可以通过遍历该属性来显示model的所有数据。
class StudentList(ListView):
model = models.Student # orm的model
template_name = 'student_list.html' # 要返回的模版文件
context_object_name = 'student_obj' # orm数据实例化对象,前端调用的名称
extra_context = {'name': 'dandy'} # 额外的上下文数据信息 def get(self, request, *args, **kwargs): # 重写get方法
response = super().get(request, *args, **kwargs)
return response def get_context_data(self, *, object_list=None, **kwargs): # 重写get_context_data方法
context = super().get_context_data(**kwargs) # 拿到返回值context并更新或者扩充
context['num'] = 11
return context def get_queryset(self):
# query_set = super().get_queryset()
# query_set = super().get_queryset()[:1]
self.kwargs['name'] = 'dandy'
cate = get_object_or_404(models.Student, name=self.kwargs.get('name'))
return super().get_queryset().filter(name=cate)
上面有一个参数没有设计到:
queryset = Student.objects.filter(name='zhangsan')
该属性表示该视图显示项的集合,可以通过get_queryset()
方法来进行定义。
所以上面的这一句筛选跟上面的get_queryset自定义的筛选,其实差不多。
context_object_name
在模板中使用object_list是一个不太友好的方法,因为不知道object_list具体指的是哪个模板的数据,因此在通用视图中还提供了一个属性:context_object_name来制定一个上下文,如:
class showStu(ListView):
...
context_object_name = "student"
看一下模版内:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h3>{{ name }}</h3>
<table>
<thead>
<td>姓名</td>
<td>年龄</td>
</thead>
<tbody>
{% for student in student_obj %}
<tr>
<td>{{ student.name }}</td>
<td>{{ student.age }}</td>
</tr>
{% endfor %}
</tbody>
</table>
<br>
<h2>{{ num }}</h2>
</body>
</html>
DetailView
继承关系:
DetailView用于显示一个特定类型对象的详细信息。DetailView的大部分属性和方法和ListView相同。不同的是该视图没有object_list
属性,因为该视图负责显示一个特定对象的详细信息,因此有一个object
属性,表示model的一个对象(或一条记录)。
class StudentDetailView(DetailView):
model = models.Student # orm的model
template_name = 'student_detail.html' # 调用的模版文件
context_object_name = 'aaa' # 模版文件里面对应的orm数据对象的名称 def get(self, request, *args, **kwargs):
response = super().get(request, *args, **kwargs) # 同样的重写的方法可以做一些自定义,比如访问量+1等等的
return response def get_object(self):
obj = super().get_object()
return obj # 这里的obj其实已经是指向一条数据了;比如一篇文章,可以进行一些修改之类的操作,obj.aa = 'dandy', obj.save() def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs) # 重写,获取返回数据
classes = self.object.classes_set.all() # 反向获取所有关联数据
context.update({ # 添加新的上下文信息
'classes': classes,
'test_name': 'dandy'
})
return context
这里需要注意的是url,因为明确表面了这个通用视图的目的,所以url固定的指向了某个具体的事物的id
path('detailview/<int:pk>/', views.StudentDetailView.as_view(), name='student_detail'),
内部形成处理。
默认情况下,DetailView 使用<appname>/<model name>_detail.html
的模板,如果没有该模板,则应该通过”template_name”指定一个模板。
Python Django CBV下的通用视图函数的更多相关文章
- Python/Django(CBV/FBV/ORM操作)
Python/Django(CBV/FBV/ORM操作) CBV:url对应的类(模式) ##====================================CBV操作============ ...
- 第三百零五节,Django框架,Views(视图函数),也就是逻辑处理函数里的各种方法与属性
Django框架,Views(视图函数),也就是逻辑处理函数里的各种方法与属性 Views(视图函数)逻辑处理,最终是围绕着两个对象实现的 http请求中产生两个核心对象: http请求:HttpRe ...
- 三 Django框架,Views(视图函数),也就是逻辑处理函数里的各种方法与属性
Django框架,Views(视图函数),也就是逻辑处理函数里的各种方法与属性 Views(视图函数)逻辑处理,最终是围绕着两个对象实现的 http请求中产生两个核心对象: http请求:HttpRe ...
- Django创建通用视图函数
想在我们有两个视图: def thinkingview(request): user = request.user if request.method == 'GET': return render( ...
- Django中使用Bootstrap----带view.py视图函数(也就是项目下的脚本文件)
一.Django中使用Bootstrap 1.首先建立工程,建立工程请参照:https://www.cnblogs.com/effortsing/p/10394511.html 2.在Firstdja ...
- Django的一些操作与视图函数
一 . Django的安装 pip install django==1.14.6 # 后面的数字是django的版本 二 . 通过命令行(cmd)来创建Django项目 1. 切换到保存项目的文件夹 ...
- python web框架篇:views视图函数
Django请求的生命周期是怎样的? 简单地说,通过URL对应关系匹配 ->找到对应的函数(或者类)->返回字符串(或者读取Html之后返回渲染的字符串) 解剖起来如下: 1. 当用户在浏 ...
- django创建app、在视图函数及url中使用参数、url命名、通过redirect实现网页路径跳转
app用来实现一个独立的功能,视图一般都写在app的view.py中,并且视图的第一个参数永远是request,视图的返回值必须是HttpResponseBase对象或子类的对象. 创建一个app:f ...
- [Python] Django框架入门3——深入视图
说明: 本文主要深入了解视图(views.py),涉及路由配置.定义视图.Request对象.Response对象.状态保持等. 一.路由配置 1.配置位置(settings.py 的 ROOT_UR ...
随机推荐
- (九)逻辑运算,order by,desc
逻辑运算 AND,OR,NOT ......where 表达式1 and 表达式2: ......where 表达式2 and 表达式1: SQL优化: SQL在解析where时是从右向左解析的. ...
- Jenkins Pipelines Summary
示例1: pipeline{ agent {label "xxx"} // label is a special machine registered in Jenkins env ...
- mysql 5.7安装准备
在5.5之后的mysql安装中,需要使用cmake来指定安装参数,下面列出关于cmake的几个常用参数: CMAKE_INSTALL_PREFIX:指定MySQL程序的安装目录,默认/usr/loca ...
- (链表) leetcode 21. Merge Two Sorted Lists
Merge two sorted linked lists and return it as a new list. The new list should be made by splicing t ...
- C# 正则表达式中的顺序环视和逆序环视
环视结构不匹配任何字符,只匹配文本中的特定位置. 顺序环视:从左向右查看文本,尝试匹配子表达式,如果能够匹配则返回匹配成功信息.顺序环视使用「 (?=...) 来标识」,例如「 (?=\d) 」,它表 ...
- angular中因异步问题产生的错误解决方法
方法一 private userTaskList(){ let auth = this.make_basic_auth("kermit","kermit"); ...
- hadoop 伪分布式搭建
下载hadoop1.0.4版本,和jdk1.6版本或更高版本:1. 安装JDK,安装目录大家可以自定义,下面是我的安装目录: /usr/jdk1.6.0_22 配置环境变量: [root@hadoop ...
- 信用评分卡Credit Scorecards (1-7)
欢迎关注博主主页,学习python视频资源,还有大量免费python经典文章 python风控评分卡建模和风控常识 https://study.163.com/course/introductio ...
- 网络编程基础【day09】:socket解决粘包问题之MD5(八)
本节内容 1.概述 2.代码实现 一.概述 上一篇博客讲到的用MD5来校验还是用的之前解决粘包的方法,就是客户端发送一个请求,等待服务端的确认的这样的一个笨方法.下面我们用另外一种方法:就是客户端已经 ...
- Oracle优化学习
SQL执行效率对系统使用有很大影响,本文总结平时排查问题中遇到的一些Oracle优化问题的解决方案,或者日常学习所得. 1. Oracle sql执行顺序 sql语法的分析是从右到左. 1.1 SQL ...