前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >Django来敲门~第一部分【9.使用Django内置视图处理对象简化开发】

Django来敲门~第一部分【9.使用Django内置视图处理对象简化开发】

作者头像
大牧莫邪
发布于 2018-08-27 09:34:54
发布于 2018-08-27 09:34:54
94900
代码可运行
举报
运行总次数:0
代码可运行

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


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

本节内容

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

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

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

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

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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路由模块

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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是怎么操作的吧

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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内置类,我们看一下源代码

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# 基础视图对象工具类,用于进行视图的渲染操作,包含了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已经封装好的对象,快捷的完成项目的开发。


本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017.06.13 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
jQuery 事件对象,拷贝对象,多库共存
jQuery 对DOM中的事件对象 event 进行了封装,兼容性更好,获取更方便,使用变化不大。事件被触发,就会有事件对象的产生。
星辰_大海
2020/10/09
4260
jQuery 事件对象,拷贝对象,多库共存
jQuery (事件、拷贝)对象
jQuery 对DOM中的事件对象 event 进行了封装,兼容性更好,获取更方便,使用变化不大。事件被触发,就会有事件对象的产生。
清出于兰
2020/10/26
6700
ECMAScript6基础学习教程(五)对象
当属性名和属性值变量同名时,ES6允许在对象中只写属性名,不写属性。 关键点有两个:
娜姐
2020/09/22
3380
jQuery笔记(4)
其他事件基本和原生一致,比如mouseover/mouseout/blur/focus...
y191024
2022/09/20
4350
jQuery笔记(4)
学习 jQuery 源码整体架构,打造属于自己的 js 类库
本文章学习的是 v3.4.1版本。unpkg.com源码地址:https://unpkg.com/jquery@3.4.1/dist/jquery.js
若川
2020/03/19
1.7K0
jQuery
onload 事件是等页面文档、外部的 js 文件、css文件、图片加载完毕才执行内部代码。
小丞同学
2021/08/16
8.6K0
面试官:你知道哪些深浅拷贝方式吗?
这个方法是可以实现拷贝的,但是我们需要注意的是,当属性对应的一个值是引用类型时,我们会发现这也是一个浅拷贝:
程序员法医
2022/08/11
2020
jQuery自动触发事件与bootstrap/jQuery插件用法
有些事件希望自动触发,比如轮播图自动播放功能跟点击右侧按钮一致。可以利用定时器自动触发右侧按钮点击事件,不必鼠标点击触发。
小城故事
2023/03/08
6.7K0
jQuery自动触发事件与bootstrap/jQuery插件用法
让你彻底理解浅拷贝和深拷贝的区别是什么_怎么让文件无法拷贝
在写js的时候经常会遇到复制对象,在复制对象的过程中往往会出现新对象改变原对象等等的一些问题,今天特意梳理一下,希望能帮助到遇到这些问题的开发人员。
全栈程序员站长
2022/11/10
5730
前端成神之路-03_jQuery
​ 因为普通注册事件方法的不足,jQuery又创建了多个新的事件绑定方法bind() / live() / delegate() / on()等,其中最好用的是: on()
海仔
2021/01/13
3.1K0
分享 4 种 JS 深拷贝的方法
浅拷贝是创建一个新对象,这个对象有着原始对象属性值的拷贝。如果属性是基本类型,拷贝的就是基本类型的值,如果属性是引用类型,拷贝的是内存地址 。
前端达人
2022/06/09
12K0
jQuery事件对象
通常情况下,只有设置操作才能把链式编程延续下去。因为获取操作的时候,会返回获取到的相应的值,无法返回 jQuery对象。
Qwe7
2022/04/17
1.6K0
「jQuery」基础 - 03
请注意,本文编写于 2071 天前,最后修改于 173 天前,其中某些信息可能已经过时。
曼亚灿
2023/05/17
2.9K0
「jQuery」基础 - 03
JavaScript学习总结(五)——jQuery插件开发与发布
jQuery插件就是以jQuery库为基础衍生出来的库,jQuery插件的好处是封装功能,提高了代码的复用性,加快了开发速度,现在网络上开源的jQuery插件非常多,随着版本的不停迭代越来越稳定好用,
张果
2018/01/04
2.9K0
JavaScript学习总结(五)——jQuery插件开发与发布
jquery和原生dom对象的转换&常用函数方法
var $p= $('p')新建一个jquery对象,一般在新建jquery对象的时候,加上一个$,以便好认。
bamboo
2019/01/29
2.3K0
jquery和原生dom对象的转换&常用函数方法
javaScript中的浅拷贝 vs 深拷贝
在前端的数据处理当中,有时候往往需要对原有的数据进行克隆拷贝一份,然后在进行操作,但是又不能影响原来的数据
itclanCoder
2020/10/28
7000
javaScript中的浅拷贝 vs 深拷贝
JS基础知识总结(二):浅拷贝与深拷贝
上一篇JS基础知识总结(一)主要了介绍变量类型相关的基础知识,本文将介绍JS的深拷贝和浅拷贝的有关内容。
前端林子
2018/12/30
2.8K0
JS基础知识总结(二):浅拷贝与深拷贝
前端基础-事件对象
事件的触发,大部分情况下是用户的一种行为,也就是说,我们并不能确定用户什么时间触发;
cwl_java
2020/03/26
4900
深拷贝 和 浅拷贝 的区别 ?
含义:假设B复制了A,当修改A时,看B是否会发生变化,如果B也跟着变了,说明这是浅拷贝,拿人手短,如果B没变,那就是深拷贝,自食其力。
青梅煮码
2023/01/16
4210
JavaScript数组(对象)的深拷贝和浅拷贝
在JavaSCript中的数据类型中,分为两种:原始类型(number/string/boolean/null/undefined)和引用类型(array/object/function)。
celineWong7
2020/11/05
2.4K0
推荐阅读
相关推荐
jQuery 事件对象,拷贝对象,多库共存
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验