探究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应用开发实战

posted @ 2021-12-02 17:03  索匣  阅读(64)  评论(0编辑  收藏  举报