探究CBV视图
CBV视图
数据显示视图
RedirectView重定向视图;
源码位置:django/views/generic/base.py
该类继承父类View,类View是所有视图类的底层功能类。
该类定义了4个属性和8个类方法
permanent:根据属性的真假来选择重定向方式,若为True,则HTTP状态码为301,否则为HTTP状态码为302.
url:代表重定向的路由地址
pattern_name:代表重定向的路由命名。如果已设置参数url,则无需设置该参数,否则提示异常信息
query_string:是否将当前路由的请求参数传递到重定向的路由地址
### 方法
get_redirect_url():根据属性pattern_name所指向的路由命名来生成相应的路由地址。
get():触发HTTP的GET请求所指向的响应处理
剩余的类方法head(),post(),options(),delete(),put()和patch()是HTTP的不同请求方式,他们都由get方法完成响应处理。
实例
class turnTo(RedirectView):
'''
RedirectView类定义了4个属性和8个类方法
对该RedirectView类功能扩展只需要重新相应的类方法即可
'''
permanent = False
url = None
pattern_name = 'index:index'
query_string = True
def get_redirect_url(self, *args, **kwargs):
print('This is get_redirect_url')
return super().get_redirect_url(*args, **kwargs)
def get(self, request, *args, **kwargs): # 只定义了重定向get的请求过程
print(request.META.get('HTTP_USER_AGENT'))
return super().get(request, *args, **kwargs)
html文件
<a href="{% url 'index:turnTo' %}?k=1">ToTurn</a>
urls文件,需要使用视图类,需要对视图类进行实例化操作as_view()方法(django/views/generic/base.py)
urlpatterns = [
# 定义路由
path('', index, name='index'),
# as_view()对视图重定向类实例化
path('turnTo', turnTo.as_view(), name='turnTo')
]
总之重定向视图get_redirect_url()函数一定要写的,该方法也只是对get请求做处理,post()请求及其他htto请求可以修改对应的类方法。
基础视图TemplateView
源码位置:django/views/generic/base.py
他继承TemplateResponseMixin, ContextMixin, View三各类。只有一个get方法
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)
该类继承的类
class TemplateResponseMixin:
"""A mixin that can be used to render a template."""
template_name = None # 设置模板文件的文件名
template_engine = None #设置解析模板文件的模板引擎
response_class = TemplateResponse #设置HTTP请求的响应类
content_type = None # 设置响应内容的数据格式
def render_to_response(self, context, **response_kwargs): # 实现响应处理,由TemplateResponse响应类完成
"""
Return a response, using the `response_class` for this view, with a
template rendered with the given context.
Pass response_kwargs to the constructor of the response class.
"""
response_kwargs.setdefault('content_type', self.content_type)
return self.response_class(
request=self.request,
template=self.get_template_names(),
context=context,
using=self.template_engine,
**response_kwargs
)
def get_template_names(self): # 获取属性template_name的值
"""
Return a list of template names to be used for the request. Must return
a list. May not be called if render_to_response() is overridden.
"""
if self.template_name is None:
raise ImproperlyConfigured(
"TemplateResponseMixin requires either a definition of "
"'template_name' or an implementation of 'get_template_names()'")
else:
return [self.template_name]
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)
class ContextMixin:
"""
A default context mixin that passes the keyword arguments received by
get_context_data() as the template context.
"""
extra_context = None
def get_context_data(self, **kwargs):
kwargs.setdefault('view', self) # 说这函数是获取视图中的上下文模板
if self.extra_context is not None:
kwargs.update(self.extra_context)
return kwargs
实例
from django.views.generic.base import TemplateView
# 视图类TemplateView是所有视图类最基础的应用视图类
class index(TemplateView):
template_name = 'index.html' # 设置模板文件
template_engine = None # 设置模板文件的模板引擎
content_type = None # 设置响应内容的数据格式
extra_context = {'title': 'This is GET'} # 模板变量设置值
# 重新定义模版上下文的获取方式
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['value'] = 'I am MyDjango'
return context
# 定义HTTP的POST请求处理
def post(self, request, *args, **kwargs):
self.extra_context = {'title': 'This is POST'}
context = self.get_context_data(**kwargs)
return self.render_to_response(context)
列表视图类ListView
将数据表的数据以列表的形式显示,常用于查询和展示。
源码位置:django/views/generic/list.py
继承MultipleObjectTemplateResponseMixin, BaseListView这两个类
class ListView(MultipleObjectTemplateResponseMixin, BaseListView):
"""
Render some list of objects, set by `self.model` or `self.queryset`.
`self.queryset` can actually be any iterable of items, not just a queryset.
"""
ListView类继承的和TemplateView类差不多,在此基础上还新增了以下属性和方法.基本上都是和数据查询,分页有关的。
实例
from django.views.generic import ListView # 将数据表的数据以列表的形式显示
from .models import PersonInfo # 需要导入模板
class index(ListView):
# 设置模版文件
template_name = 'index.html'
# 设置模型外的数据
extra_context = {'title': '人员信息表'}
# 查询模型PersonInfo
queryset = PersonInfo.objects.all() # 这个一定要填,这是向该类传入数据库查询对象
# 每页的展示一条数据
paginate_by = 1
# 意思就是数据库的模板对象,在html页面可调用数据
# 如不设置,则模版上下文默认为personinfo_list;就是数据库名_list
# context_object_name = 'personinfo'
详细视图类DetailView
是将数据库某一条数据详细显示在网页上
源码位置:django/views/generic/detail.py
该类与ViewList视图类在继承上面有一定的相似之处。同时也具有TemplateView的所有属性和方法,并新增了以下属性和方法
用时再找
实例views.py
from django.views.generic import DetailView # 详细视图DetailVie是将数据库某一条数据详细显示在网页上
from .models import PersonInfo
class index(DetailView):
# 设置模版文件
template_name = 'index.html'
# 设置模型外的数据
extra_context = {'title': '人员信息表'}
# 设置模型的查询字段
slug_field = 'age' # 可以根据路由名,get方法来查询数据库,url?age=xxx之类的
# 设置路由的变量名,与属性slug_field实现模型的查询操作
slug_url_kwarg = 'age' # 用于查询模型的其他字段
pk_url_kwarg = 'pk' # 用于查询模型的主键
# 设置查询模型PersonInfo
model = PersonInfo #
# 属性queryset可以做简单的查询操作
# queryset = PersonInfo.objects.all()
# 如不设置,则模版上下文默认为personinfo
# context_object_name = 'personinfo' # context_object_name属性,模型对象用模型类的小写表示
# 是否将pk和slug作为查询条件
# query_pk_and_slug = False # 为false则优先查询pk_url_kwarg
实例urls.py
urlpatterns = [
# 定义路由<>参数来源于views.py中的查询数据库字段
path('<pk>/<age>.html', index.as_view(), name='index'),
]
数据操作视图
对模型进行操作,如增、删、改,从而实现Django与数据库的数据交互。有四个视图类
FormView
表单视图类:通过表单实现数据验证、响应输出等功能,用于显示表单数据
源码位置:
django/views/generic/edit.py
继承自两个视图TemplateResponseMixin, BaseFormView
class FormView(TemplateResponseMixin, BaseFormView):
"""A view for displaying a form and rendering a template response."""
还和基本视图类TemplateView一样,但新增了些属性和方法
待补
实例views.py
from django.views.generic.edit import FormView # 表单视图类
from .form import PersonInfoForm
from django.http import HttpResponse
def result(request):
return HttpResponse('Success')
class index(FormView): # 该例子就是点击之后,跳转成功页面有success_url提供路由
initial = {'name': 'Betty', 'age': 20} # 设置默认初始的表单值
template_name = 'index.html' # 定义模型表单
success_url = '/result' # 为success_url属性提供路由
form_class = PersonInfoForm # 表单的实例化,在html页面所使用的模板变量为form.as_p,
# 这命名固定的,是由FormMixin类的get_context_data()函数生成
extra_context = {'title': '人员信息表'} # 模板上下文
urls.py
urlpatterns = [
# 定义路由
path('', index.as_view(), name='index'),
path('result', result, name='result')
]
表单视图类肯定要创建表单forms.py,最基本的表单类(这里是模型表单)
from django import forms
from .models import PersonInfo
class PersonInfoForm(forms.ModelForm):
class Meta:
model = PersonInfo
fields = '__all__'
CreateView新增视图
是对模型新增数据的视图类,他是在表单视图类FormView类的基础上加以封装的
源码位置:django/views/generic/edit.py
继承自SingleObjectTemplateResponseMixin, BaseCreateView这两个类
class CreateView(SingleObjectTemplateResponseMixin, BaseCreateView):
"""
View for creating a new object, with a response rendered by a template.
"""
template_name_suffix = '_form'
到目前为止,几乎所有的视图类都会继承TemplateResponseMixin,除了重定向视图类RedirectView
新增属性和方法:
待补
有两种表单生成方式,第一种是设置属性form_class,通过属性form_class指定表单对象,这种方式需要开发者自行定义表单对象。加入自定义的表单和模型的字符不相符,在运行过程中会出现异常情况,第二种设置model和fields属性。由模型对象和模型字段来生成相应的表单对象,生成的表单字段与模型的字段要求相符。
实例
views.py
from django.views.generic.edit import CreateView# 是对模型新增数据的视图类,他是在表单视图类FormView类的基础上加以封装的
from .form import PersonInfoForm
from .models import PersonInfo
from django.http import HttpResponse
def result(request):
return HttpResponse('Success')
class index(CreateView): # 字段设置除了表单生成和之前的表单视图类似
initial = {'name': 'Betty', 'age': 20}
template_name = 'index.html'
success_url = '/result'
# 表单生成方式一
# form_class = PersonInfoForm
# 表单生成方式二
model = PersonInfo
# fields设置模型字段,从而生成表单字段
fields = ['name', 'age']
extra_context = {'title': '人员信息表'}
html
<head>
<title>{{ title }}</title>
<body>
<h3>{{ title }}</h3>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="确定">
</form>
</body>
UpdateView 修改视图
该类的实现是在FormView和DetailView类基础上实现的。是通过路由查询数据,在后再通过表单修改数据。
源码位置:django/views/generic/edit.py
继承自SingleObjectTemplateResponseMixin, BaseUpdateView这两个类
class UpdateView(SingleObjectTemplateResponseMixin, BaseUpdateView):
"""View for updating an object, with a response rendered by a template."""
template_name_suffix = '_form'
实例:
views.py
from django.views.generic.edit import UpdateView # 修改视图
from .models import PersonInfo
from django.http import HttpResponse
def result(request):
return HttpResponse('Success')
class index(UpdateView):
template_name = 'index.html'
success_url = '/result'
model = PersonInfo
# fields设置模型字段,从而生成表单字段
fields = ['name', 'age']
slug_url_kwarg = 'age'
slug_field = 'age'
context_object_name = 'personinfo'
extra_context = {'title': '人员信息表'}
urls.py
urlpatterns = [
# 定义路由
path('<age>.html', index.as_view(), name='index'),
path('result', result, name='result')
]
DeleteView 删除视图
只能删除单条数据,路由变量为模型主键提供查询范围。查询出来的数据通过POST请求实现数据删除,删除过程由类DeletionMixin的delete()方法实现。
源码位置:django/views/generic/edit.py
继承自SingleObjectTemplateResponseMixin, BaseDeleteView这两个类
class DeleteView(SingleObjectTemplateResponseMixin, BaseDeleteView):
"""
View for deleting an object retrieved with self.get_object(), with a
response rendered by a template.
"""
template_name_suffix = '_confirm_delete'
实例views.py
from django.views.generic.edit import DeleteView # 删除视图
from .models import PersonInfo
from django.http import HttpResponse
def result(request):
return HttpResponse('Success')
class index(DeleteView):
template_name = 'index.html'
success_url = '/result'
model = PersonInfo
context_object_name = 'personinfo'
extra_context = {'title': '人员信息表'}
urls.py
去掉.html留数字执行路由跳转时候报错
from django.urls import path
from .views import *
urlpatterns = [
# 定义路由pk,来自属性pk_url_kwarg,默认值为pk,可在SingleObjectMixin类中找到
# 尽量不要使用数字单独做后缀,不加.html,容易报错ValueError: invalid literal for int() with base 10:
path('<pk>.html', index.as_view(), name='index'),
path('result', result, name='result')
]
日期筛选视图
是根据某个日期字段进行数据筛选的,然后将符合结果的数据以一定的形式显示在网页上。在列表视图ListView或详细视图DetailView的基础上增加日期筛选所实现的视图类。一共有7个日期视图类
1.ArchiveIndexView 是将数据表所有的数据以某个日期字段的降序方式进行排序显示的。
2.YearArchiveView是在数据表筛选某个日期字段某年的所有数据,默认以升序的方式排序显示,年份的筛选范围由路由变量提供。
3.MonthArchiveView是在数据表筛选某个日期字段某年某月的所有的数据,默认以升序的方式排序显示。
4.WeekArchiveView是在数据表筛选某个日期字段某年某周的所有的数据,总周数是将一年的总天数除以7所得的,数据默认以升序的方式排序显示,年份和周数的筛选范围都是由路由变量提供的。
5.DayArchiveView是对数据表的某个日期字段精准筛选到某年某月某天,将符合条件的数据以升序的方式排序显示,年份,月份和天数都是由路由变量提供的
6.TodayArchiveView是在视图DayArchiveView的基础上进行封装的,他将数据表某个日期字段的筛选条件设为当天时间,符合条件的数据以升序的方式排序显示
7.DateDetailView是查询某年某月某日某条数据的详细信息,在视图类DetailView类的基础上增加了日期筛选功能,筛选条件主要有年份、月份、天数和某个模型字段,其中某个模型字段必须具有唯一性,才能确保查询数据的唯一性。
是在数据表筛选某个日期字段某年某月的所有数据,默认以升序的方式排序显示
MonthArchiveView 月份视图
源码位置:django/views/generic/dates.py
继承MultipleObjectTemplateResponseMixin, BaseWeekArchiveView这两个类
class WeekArchiveView(MultipleObjectTemplateResponseMixin, BaseWeekArchiveView):
"""List of objects published in a given week."""
template_name_suffix = '_archive_week'
为什么不在这里写新增方法,属性,太多了
实例
views.py
from django.views.generic.dates import MonthArchiveView #是在数据表筛选某个日期字段某年某月的所有数据,默认以升序的方式排序显示
from .models import PersonInfo
class index(MonthArchiveView):
allow_empty = True
allow_future = True
context_object_name = 'mylist'
template_name = 'index.html'
model = PersonInfo
date_field = 'hireDate' # 日期数据筛选
queryset = PersonInfo.objects.all()
year_format = '%Y'
# month_format默认格式是支持英文日期,如Oct、Sep
month_format = '%m' # 默认值为%b,mouth在url中的属性是整型,所以改为%m
paginate_by = 50
urls.py
from django.urls import path
from .views import *
urlpatterns = [
# 定义路由
path('<int:year>/<int:month>.html', index.as_view(), name='index'),
# path('<int:year>/<str:month>.html', index.as_view(), name='index'),
]
html文件
<body>
<ul>
{% for v in object_list %}<!--由模型查询所得的数据对象,默认为object_list或者page_obj(常用在分页)-->
<li>{{ v.hireDate }}: {{ v.name }}</li>
{% endfor %}
</ul>
<p>
{% if previous_month %}
Previous Month: {{ previous_month }} <!--根据路由变量year和month的日期计算出上一个月的日期-->
{% endif %}
<br>
{% if next_month %}<!--下一个月日期-->
Next Month: {{ next_month }}
{% endif %}
</p>
</body>
WeekArchiveView 周期视图
是在数据表筛选某个日期字段某年某周的所有的数据
源码位置:django/views/generic/dates.py
继承自MultipleObjectTemplateResponseMixin, BaseWeekArchiveView这两个类。
class WeekArchiveView(MultipleObjectTemplateResponseMixin, BaseWeekArchiveView):
"""List of objects published in a given week."""
template_name_suffix = '_archive_week'
实例views.py
from django.views.generic.dates import WeekArchiveView # 是在数据表筛选某个日期字段某年某周的所有的数据
from .models import PersonInfo
class index(WeekArchiveView):
allow_empty = True
allow_future = True # 设置是否显示未来日期的数据,如产品有效期
context_object_name = 'mylist'
template_name = 'index.html'
model = PersonInfo
date_field = 'hireDate' # 日期数据筛选
queryset = PersonInfo.objects.all()
year_format = '%Y'
week_format = '%W' # 改变的地方和上个相比
paginate_by = 50
urls.py
from django.urls import path
from .views import *
urlpatterns = [
# 定义路由;最好设置为整型,不同的数据类型会影响视图类MonthArchiveView的属性month_format的值。
path('<int:year>/<int:week>.html', index.as_view(), name='index'),
]
知识点as.view()实例化视图类,写在视图函数中(urls.py中也可以,只要那里导入了视图类)
笔记来源:Django Web应用开发实战