文档章节

django类视图浅析

人间四月
 人间四月
发布于 2016/04/19 09:45
字数 1431
阅读 23
收藏 0

在Django1.3之前,通用视图是以函数的方式来实现的。基于函数的实现已经不 建议使用,建议使用这里介绍的基于类的实现方式。

基于类的通用视图(以及任何继承了Django提供的基础类的基于类的视图)都能够以下面两种方式被配置:子类化,或者直接通过URLconf来传递参数。

简单使用

当你子类化一个类视图时,你可以重写一些属性(比如template_name)或者 一些方法(比如 get_context_data)在你的子类中来提供一些新的值或者方 法。考虑一下,比如,一个仅仅需要展示一个模板的视图,about.html。Django有一个通用视图来完成这个功能 - TemplateView - 因此你可以子类化它,然后重写模板的名称:

# some_app/views.py
from django.views.generic import TemplateView
class AboutView(TemplateView):
    template_name = "about.html"

这时,你只需要添加这个新的视图到你的URLconf配置中。因为类视图本身是一个类,我 们把URL指向 as_view 这个类方法来替代类本身,这是类视图的入口点:

# urls.py
from django.conf.urls import patterns, url, include
from some_app.views import AboutView
urlpatterns = patterns('',
    (r'^about/', AboutView.as_view()),)

作为一个选择,如果你仅仅修改类视图中少量简单的属性,你可以直接传递新的属性 到类本身调用 as_view 方法中:

from django.conf.urls import patterns, url, include
from django.views.generic import TemplateView
urlpatterns = patterns('',
    (r'^about/', TemplateView.as_view(template_name="about.html")),)

一个类似的重写模式可以用在 RedirectView 的 url 属性上,这是另外一个简单的通用视图。

Minin

如果要深入理解class-based view, 那首先就要了解什么是Mixin! Django把基本的http请求和响应抽象出来, 封装成各自的类, 在使用过程中只需把各个基类聚合到一起使用, 并按照自己的要求重写自己需要的方法就可以了, 那么就把这些基类叫Mixin吧. 在Django中比较基础的Mixin主要有几类:

  1. View(视图基础类)

  2. SingleObjectMixin(单对象类)

  3. MultipleObjectMixin(多对象类)

  4. TemplateResponseMixin(模板响应类)

  5. FormMixin(表单类)

  6. YearMixin, MonthMixin, DayMixin, WeekMixin, DateMixin(几个基于时间关系的类)

其他的所有内置class-based view都是把以上几个基础类组合, 重写方法以达到预期的结果. 比如DetailView这个类就组合了SingleObjectTemplateResponseMixin和BaseDetailView.

对象的通用视图

TemplateView确实很有用,但是你可能需要把数据库中的内容查询展示出来,没关系,Django同样提供了大把内置的通用视图。下面看一个简单例子:

# models.py
from django.db import models
class Publisher(models.Model):
    name = models.CharField(max_length=30)
    address = models.CharField(max_length=50)
    city = models.CharField(max_length=60)
    state_province = models.CharField(max_length=30)
    country = models.CharField(max_length=50)
    website = models.URLField()
    class Meta:
        ordering = ["-name"]
    def __unicode__(self):
        return self.nameclass Book(models.Model):
    title = models.CharField(max_length=100)
    authors = models.ManyToManyField('Author')
    publisher = models.ForeignKey(Publisher)
    publication_date = models.DateField()

为了给所有的Publisher建立一个列表页,我们将按照这样的方式来配置URLconf:

from django.conf.urls import patterns, url, include
from django.views.generic import ListView
from books.models import Publisher
urlpatterns = patterns('',
    (r'^publishers/$', ListView.as_view(
        model=Publisher,template_name=’publisher_list.html‘,
    )),)

下面是简单的模板实例:

{% extends "base.html" %}
{% block content %}
    <h2>Publishers</h2>
    <ul>
        {% for publisher in object_list %}
            <li>{{ publisher.name }}</li>
        {% endfor %}
    </ul>
{% endblock %}

扩展通用视图

使用通用视图可以极大的提高开发速度。然而,在大多时候我们会发现通用视图无法满足需求。为此,我们可以对通用视图进行扩展来增加自己的功能。扩展通用视图的方法是子类化它们,并且重写它们的属性或者方法。

编写”友好的”模板

默认情况下,通用视图将所有相关Model的查询到的对象放到object_list变量中,这虽然能正常工作,但是对模板设计者不友好。

通用视图中的这个属性 : context_object_name指定上下文(context)变量要使用的名字。在这个例子中我们在URLconf中重写了它,因为这只是简单的修改:

urlpatterns = patterns('',
    (r'^publishers/$', ListView.as_view(
        model=Publisher,
        template_name=”publisher_list.html“,
        context_object_name="publisher_list",
    )),)

我们应该使用context_object_name来指定上下文(context)变量。

添加额外的上下文

我们可能需要一些通用视图没有提供的额外信息,我们可以子类化DetailView然后提供你自己的 get_context_data方法的实现。

DetailView 中默认的实现只是简单的 给模板添加了要展示的对象,但是你这可以这么重写来展示更多信息:

from django.views.generic import DetailView
from books.models import Publisher, Book
class PublisherDetailView(DetailView):
    context_object_name = "publisher"
    model = Publisher
    def get_context_data(self, **kwargs):
        # Call the base implementation first to get a context
        context = super(PublisherDetailView, self).get_context_data(**kwargs)
        # Add in a QuerySet of all the books
        context['book_list'] = Book.objects.all()
        return context

查看对象的子集合

model参数指定了视图(view)在哪个数据库模型之上进行操作,但是这个太不灵活了,我们可以使用 queryset参数来指定一个对象列表:

from django.views.generic import DetailView
from books.models import Publisher, Book
class PublisherDetailView(DetailView):
    context_object_name = "publisher"
    queryset = Publisher.objects.all()

指明model = Publisher 等价于快速声明的queryset = Publisher.objects.all() 。然而,使用 queryset可以定义一个过滤的对象列表:

from django.views.generic import ListView
from books.models import Book
class AcmeBookListView(ListView):
    context_object_name = "book_list"
    queryset = Book.objects.filter(publisher__name="Acme Publishing")
    template_name = "books/acme_list.html"

动态URL

另一个普遍的需求是在给定的列表页面中根据URL中的关键字来过滤对象。ListView 有一个 get_queryset() 方法来供我们重写。
这里,我们有一个URLconf定义了一组供捕获的参数:

from books.views import PublisherBookListView
urlpatterns = patterns('',
    (r'^books/(\w+)/$', PublisherBookListView.as_view()),)

下一个,我们定义了 PublisherBookListView 视图:

from django.shortcuts import get_object_or_404
from django.views.generic import ListView
from books.models import Book, Publisher
class PublisherBookListView(ListView):
    context_object_name = "book_list"
    template_name = "books/books_by_publisher.html"
    def get_queryset(self):
        publisher = get_object_or_404(Publisher, name__iexact=self.args[0])
        return Book.objects.filter(publisher=publisher)

参考资料

http://django-14-tkliuxing.readthedocs.org/en/latest/topics/class-based-views.html
http://simple-is-better.com/news/643
http://simple-is-better.com/news/644

本文转载自:http://blog.csdn.net/duomoke/article/details/46458823

共有 人打赏支持
上一篇: Class-based View
下一篇: Mixin
人间四月
粉丝 2
博文 74
码字总数 30455
作品 0
朝阳
程序员
私信 提问
详解Django的CSRF认证

1.csrf原理 2.Django中的CSRF中间件 首先,我们知道Django中间件作用于整个项目。 在一个项目中,如果想对全局所有视图函数或视图类起作用时,就可以在中间件中实现,比如想实现用户登录判断...

任平生78
10/08
0
0
Django 基于类的视图源码分析 一

基于类的视图(Class-based view)是Django 1.3引入的新的视图编写方式,用于取代以前基于函数(Function-based)方式。借助于OO和Python中方便的多重继承特性,基于类的视图可以提供更好的抽象与...

XuYuan
2013/02/05
0
0
LET'S DJ:web.py无缝迁移到django

DO: 前提是必须要配置好django使用jinja2模版,保持与老项目模版引擎一致。 Django通用视图最基础的类是View,其他如TemplateView、RedirectView等都继承自它,具体用法参见:Django 通用视...

cwalet
2016/04/29
241
0
史上最友好的 Django 入门教程

Django是使用Python开发的开源Web开发框架。使用Django,你能以最小的代价构建和维护高质量的Web应用。 我们参考Django 官方文档,制作了一门新手更容易理解的Django 基础教程 ,帮助大家更好...

实验楼
07/26
0
0
android自学笔记《四》——应用程序结构分析

昨天在帖子里看到的一个分析方法,很简单,给大家分享下! 呵呵,由于我也是刚开始学习Android,还没有学到下面这些知识,这里就直接截图了。 看完他这个分析之后,我对Android程序有了一个简...

郭子
2012/02/03
0
1

没有更多内容

加载失败,请刷新页面

加载更多

[LintCode] Serialize and Deserialize Binary Tree(二叉树的序列化和反序列化)

描述 设计一个算法,并编写代码来序列化和反序列化二叉树。将树写入一个文件被称为“序列化”,读取文件后重建同样的二叉树被称为“反序列化”。 如何反序列化或序列化二叉树是没有限制的,你...

honeymose
今天
5
0
java框架学习日志-7(静态代理和JDK代理)

静态代理 我们平时去餐厅吃饭,不是直接告诉厨师做什么菜的,而是先告诉服务员点什么菜,然后由服务员传到给厨师,相当于服务员是厨师的代理,我们通过代理让厨师炒菜,这就是代理模式。代理...

白话
今天
23
0
Flink Window

1.Flink窗口 Window Assigner分配器。 窗口可以是时间驱动的(Time Window,例如:每30秒钟),也可以是数据驱动的(Count Window,例如:每一百个元素)。 一种经典的窗口分类可以分成: 翻...

满小茂
今天
18
0
my.ini

1

architect刘源源
今天
16
0
docker dns

There is a opensource application that solves this issue, it's called DNS Proxy Server It's a DNS server that solves containers hostnames, if could not found a hostname that mat......

kut
今天
16
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部