美文网首页Django来敲门程序员
Django来敲门~第一部分【9.使用Django内置视图处理对

Django来敲门~第一部分【9.使用Django内置视图处理对

作者: 大牧莫邪 | 来源:发表于2017-06-13 17:58 被阅读167次

常使民无知、无欲,使夫智者不敢为也。为无为,则无不治
——老子《道德经》


首先,要说这是Django基础部分的最后一个章节了。后面会详细讲解Django每一部分的使用方式和API了

本节内容

  • 内置视图处理对象的定义
  • 内置视图处理对象的使用
  • 源代码分析

1. 内置视图处理对象的定义

对于我们视图处理函数,从最原始的HttpResponse()来进行页面数据的输出,到render()函数进行模板页面的操作,已经是可以满足我们的需求了,但是Django赶脚还不够,不够~所以提供了常规的一些页面视图对象对页面模板和模板中要展示的数据进行了封装处理。

常规情况下,对应页面中要展示数据列表的视图,通过继承Django的django.views.generic.ListView对象来实现,页面中要展示数据信息的视图,通过继承Django的django.views.generic.DetailView进行实现。

我们改造polls/views.py视图模块如下:

from django.shortcuts import render, get_object_or_404

from django.http import HttpResponseRedirect
from django.views import generic
from django.urls import reverse

from .models import Question


# 封装:定义展示应用首页的处理类
class IndexView(generic.ListView):
    # 模板路径
    template_name = "index.html"
    # 指定变量名称,保存查询到的数据
    context_object_name = "question_list"

    # 列表页面,需要查询对应的数据集合
    def get_queryset(self):
        return Question.objects.order_by("-pub_date")


# 封装:定义展示问题详细信息的处理类
class DetailView(generic.DetailView):
    # 指定要展示的数据类型
    model = Question
    # 指定展示的模板页面
    template_name = "details.html"


# 封装:定义展示结果的视图处理类
class ResultView(generic.DetailView):
    model = Question
    template_name = "results.html"


# 定义投票结果
def vote(request, question_id):
    # 获取查询的问题对象
    question = get_object_or_404(Question, pk=question_id)
    print(request.POST)
    try:
        select_choice = question.choice_set.get(pk=request.POST['choice'])
    except Exception as e:
        print(e)
        return render(request, "details.html",
                      {
                          "question": question,
                          "error_message": "你的问题还没有发布解决方案"
                      })
    else:
        # 投票数量增加1
        select_choice.votes += 1
        # 保存到数据库
        select_choice.save()
        # 代码中使用配置的方式跳转到指定的路由
        return HttpResponseRedirect(reverse("polls:results", args=(question.id,)))

上述代码中,对于展示问题列表的首页,继承了generic.ListView内置类,通过template_name指定了HTML视图,通过context_object_name指定了保存数据的变量,在get_queryset()函数中定义了数据的查询方式

问题详细信息页面和问题解决方案的结果展示页面,继承了generic.DetailView内置类,通过model指定了展示的数据的类型,template_name指定了HTML视图的名称

vote函数暂时不做任何处理,这是一个包含了业务逻辑处理的视图函数

2. 视图对象的使用

经过上述的改造,我们可以看到视图处理函数已经变得非常的简洁,但是存在这样一个问题,IndexView处理类中的数据,我们可以看懂是通过get_queryset()函数进行查询的,然后自动复制给变量question_list,那么后面的DetailViewResultView中的数据是怎么来的呢?

DetailViewResultView中的要查询的数据,同样也是通过主键编号进行查询的,默认的变量名称是pk,所以在路由中要进行如下的修改配置,才可以正常使用

改造polls/urls.py路由模块

from django.conf.urls import url
from . import views

app_name = "polls"

urlpatterns = [
    # url(r"^$", views.index, name="index"),
    # url(r"^(?P<question_id>\d+)$", views.detail, name="detail"),
    # url(r"^(?P<question_id>\d+)/results/$", views.results, name="results"),
    url(r"^$", views.IndexView.as_view(), name="index"),
    url(r"^(?P<pk>\d+)/$", views.DetailView.as_view(), name="detail"),
    url(r"^(?P<pk>\d+)/results/$", views.ResultView.as_view(), name="results"),
    url(r"^(?P<question_id>\d+)/vote/$", views.vote, name="vote"),
]

这里路由配置的过程中,通过as_view()函数,会自动对目标视图类进行封装,将视图处理类中的template_name模板进行加载,然后渲染由model或者context_object_name指定的数据。

2.1. 项目测试

重启项目,打开网页进行访问

访问首页
查看问题
投票操作

3. 源码分析

此时,会有个问题困扰着我们,为什么要继承视图处理类,为什么要继承不同的处理类ListViewDetailView

这个问题就对了,我们看看Django源代码

首先查看ListView

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.
    """
......
class MultipleObjectMixin(ContextMixin):
    """
    A mixin for views manipulating multiple objects.
    """
    allow_empty = True 
    queryset = None
    model = None
    paginate_by = None
    paginate_orphans = 0
    context_object_name = None
    paginator_class = Paginator
    page_kwarg = 'page'
    ordering = None
......
    def get_queryset(self):
        """
        Return the list of items for this view.

        The return value must be an iterable and may be an instance of
        `QuerySet` in which case `QuerySet` specific behavior will be enabled.
        """
......

我们可以从上述代码中看到,继承自ListView视图处理类的类型,已经在内部封装好了分页操作功能,这也是我们项目中经常用到的技术呢,非常棒吧,我们继承了这个视图处理对象,就可以在后续的项目中,通过重写它的属性和方法来快捷的完成数据展示的分页功能了。

接下来,我们继续看DetailView是怎么操作的吧

class DetailView(SingleObjectTemplateResponseMixin, BaseDetailView):
    """
    Render a "detail" view of an object.

    By default this is a model instance looked up from `self.queryset`, but the
    view will support display of *any* object by overriding `self.get_object()`.
    """
......
class SingleObjectMixin(ContextMixin):
    """
    Provides the ability to retrieve a single object for further manipulation.
    """
    model = None
    queryset = None
    slug_field = 'slug'
    context_object_name = None
    slug_url_kwarg = 'slug'
    pk_url_kwarg = 'pk'
    query_pk_and_slug = False  
......

我们可以在源代码中,看到各种操作的一些信息,官方注释用于使用对象数据来渲染详细信息页面的视图对象,继承的父类中,也定义了各种属性字段用于控制单个对象数据的展示操作

以上两个视图类,都间接继承了View内置类,我们看一下源代码

# 基础视图对象工具类,用于进行视图的渲染操作,包含了as_view()处理函数
class View(object):
    """
    Intentionally simple parent class for all views. Only implements
    dispatch-by-method and simple sanity checking.
    """
    ......
    @classonlymethod
    def as_view(cls, **initkwargs):
        """
        Main entry point for a request-response process.
        """
        for key in initkwargs:
        ......
# 用于进行视图模板和数据混合渲染的工具类,可以看到包含了template_name字段
class TemplateResponseMixin(object):
    """
    A mixin that can be used to render a template.
    """
    template_name = None
    template_engine = None
    response_class = TemplateResponse
    content_type = None
......
# 用于封装基础模板渲染页面视图的工具类
class TemplateView(TemplateResponseMixin, ContextMixin, View):
    """
    A view that renders a template.  This view will also pass into the context
    any keyword arguments passed by the URLconf.
    """
......
# 用于请求最终重定向的视图工具类
class RedirectView(View):
    """
    A view that provides a redirect on any GET request.
    """
......

从基础文件view.py中,我们可以看到,各种视图模板的基础处理操作和视图类型的封装都有了简洁的定义,我们需要做的就是在项目中,继承这些Django已经封装好的对象,快捷的完成项目的开发。


Django来敲门

相关文章

  • Django来敲门~第一部分【9.使用Django内置视图处理对

    常使民无知、无欲,使夫智者不敢为也。为无为,则无不治——老子《道德经》 首先,要说这是Django基础部分的最后一...

  • Django实现用户密码重置

    使用Django内置的认证视图实现简单的通过邮箱重置密码的功能版本:django 1.11 在django.con...

  • Django视图和模型

    Django视图和模型 创建项目helloworld1 使用 django-admin 来创建 helloworl...

  • 认证视图

    Django提供了几个视图,可用于处理登录,注销和密码管理。 这些使用内置的认证表单,但你也可以传入你自己的表单。...

  • django(十一)自定义404、403页面

    1.直接覆盖内置视图 templates/404.html 内容: 默认会调用内置视图 django.views....

  • Django 框架之 Django信号

    知识点 概念 如何监听信号 Django内置信号 自定义信号 使用Django内置信号 概念 Django 提供一...

  • django 自带auth 模块小记

    创建用户 修改密码 User属性 User方法 登陆和退出 Django 提供内置的视图(view)函数用于处理登...

  • 七、DRF之视图

    写在前面-->视图回顾: Django视图的使用 Django的函数视图:注意这里的 request 和 resp...

  • Django-类视图

    一、思考 如何在一个视图中处理get和post请求 二、类视图使用 在Django中也可以使用类来定义一个视图,称...

  • django 类视图解析 -FormView

    django 类视图可以帮我们轻松处理特定功能的逻辑,django 基本类视图分为四类: 基础类视图:ViewTe...

网友评论

本文标题:Django来敲门~第一部分【9.使用Django内置视图处理对

本文链接:https://www.haomeiwen.com/subject/rcjdqxtx.html