基于类的通用视图

基于类的通用视图

前面我们说过了django的通用视图,不知道django通用视图的去看我前面的随笔,谢谢

django的通用视图帮我们省略了很多代码,但有时候django的通用视图并不能满足我们全部的需求,例如像重定义一些属性和方法的时候,或者我们想换种写法的时候,因此,django提供了基于类的通用视图,通过子类或者在url中传参的方法来配置我们的基于类的通用视图

通用视图和基于类的通用视图是两种不一样的写法,前面我们介绍的通用视图,所有的代码集中于url的配置文件中,而基于类的通用视图主要集中于配置“继承然后覆盖父类方法和属性”方面

简单用法

考虑你仅仅想要显示一个模板about.html,django提供了一个通用视图去做这件事,我们只需要继承它,然后覆盖覆盖模板名称即可,其实TemplateView类对应的是direct_to_template

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

然后再url配置文件中直接调用相应的方法即可

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

或者我们可以直接在url中通过传参的方法达到修改属性的目的

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")),
)

对象的通用视图

首先这是我们可能会用到的model

# 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.name
class Book(models.Model):
    title = models.CharField(max_length=100)
    authors = models.ManyToManyField(‘Author‘)
    publisher = models.ForeignKey(Publisher)
    publication_date = models.DateField()

为了生成一个所有出版商的页面,我们可以在url中这样写

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,
    )),
)

在这里我们没有指定模板名,那么会使用ListView默认的模板名默认模板<app_label>/<model_name>_list.html ,这里可能是/books/publisher_list.html

拓展通用视图

制作友好的模板上下文名称

如果你在和模型打交道,使用下面的配置可以使你自己定义一个更好用(django内部有规则生成一个)的模板上下文名称,这可能使得和你合作的模板设计师对你有好感,因为有时候django自动生成的模板上下文名称很冗长

urlpatterns = patterns(‘‘,
    (r‘^publishers/$‘, ListView.as_view(
        model=Publisher,
        context_object_name="publisher_list",
    )),
)

增加额外的上下文内容

有时候默认的通用视图提供的上下文内容不能满足你的需求,比如一个返回所有出版商的列表的页面,上面可能一点和书籍的信息都没有,这时候你可以通过继承相应的父类,覆盖父类的方法为子类添加额外的内容

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属性和queryset属性,model=Publisher和queryset=Publisher.objects.all()基本是一致的,基于这一点,我们可以通过制定queryset的方法以至于不必每次都收返回一个模型的全集,可以每次只返回一个子集,当然,我们也可以在url中达到这个目标

urlpatterns = patterns(‘‘,
    (r‘^publishers/$‘, ListView.as_view(
        queryset=Publisher.objects.all(),
        context_object_name="publisher_list",
    )),
    (r‘^books/$‘, ListView.as_view(
        queryset=Book.objects.order_by("-publication_date"),
        context_object_name="book_list",
    )),
)
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中,但如果我们要写一个能够根据任意给定的出版商,返回该出版商的所有书籍的视图呢?我们可以覆盖get_queryset()这个方法

    def get_queryset(self):
        publisher = get_object_or_404(Publisher, name__iexact=self.args[0])
        return Book.objects.filter(publisher=publisher)

执行额外的工作

假如Author这个模型有一个last_accessed的date类型属性,我们要求每次访问的时候都更新这个属性,显然,django的通用视图是根本不知道Author有这样的一个属性的,所以我们必须重写某个方法以增加这个行为,在这里是get_object()方法

import datetime
from books.models import Author
from django.views.generic import DetailView
from django.shortcuts import get_object_or_404
class AuthorDetailView(DetailView):
    queryset = Author.objects.all()
    def get_object(self):
        # Call the superclass
        object = super(AuthorDetailView, self).get_object()
        # Record the last accessed date
        object.last_accessed = datetime.datetime.now()
        object.save()
        # Return the object
        return object

装饰基于类的视图

在url中装饰

from django.contrib.auth.decorators import login_required, permission_required
from django.views.generic import TemplateView
from .views import VoteView
urlpatterns = patterns(‘‘,
    (r‘^about/‘, login_required(TemplateView.as_view(template_name="secret.html"))),
    (r‘^vote/‘, permission_required(‘polls.can_vote‘)(VoteView.as_view())),
)

在类中装饰

from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator
from django.views.generic import TemplateView
class ProtectedView(TemplateView):
    template_name = ‘secret.html‘
    @method_decorator(login_required)
    def dispatch(self, *args, **kwargs):
        return super(ProtectedView, self).dispatch(*args, **kwargs)

p

时间: 2024-12-17 12:14:52

基于类的通用视图的相关文章

Django——基于类的视图(class-based view)

刚开始的时候,django只有基于函数的视图(Function-based views).为了解决开发视图中繁杂的重复代码,基于函数的通用视图( Funcation-based generic views)出现了,但是不久它的弊端就显示出来:无法扩展.无法定制.基于函数的通用视图的不灵活导致它在现实世界中的应用受限.基于类的通用视图也是出于同样的目的被开发出来,它提供一个工具箱(基类)并支持多重继承,随着它的应用,人们发现它的可扩展性和灵活性远超它的小兄弟——基于函数的通用视图. 基于类的通用视

Django——基于类的视图源码分析 一

基于类的视图(Class-based view)是Django 1.3引入的新的视图编写方式,用于取代以前基于函数(Function-based)方式. 借助于OO和Python中方便的多重继承特性,基于类的视图可以提供更好的抽象与复用能力. 新的通用视图将更加优雅. Django的文档较为丰富,但在实际开发中往往仍显得不够,很多时候还是需要深入到源代码当中一探究竟.为此,仔细整理了一下基于类的视图的实现方式.期望对以后的开发能够提供更加清晰.直接的参考. 说明: Django大量应用了多重继承

Django编写RESTful API(三):基于类的视图

欢迎访问我的个人网站:www.comingnext.cn 前言 在上一篇文章中,主要讲的是请求和响应,项目里面views.py中的视图函数都是基于函数的,并且我们介绍了@api_view这个很有用的装饰器.同时,我们还介绍了APIView这个类,但是还没使用它.在这篇文章中,我们要做的是把基于方法的视图改为基于类的视图,将会了解到APIView. 改为基于类的视图 重构一下snippets/view.py: from snippets.models import Snippet from sni

Django——基于类的视图源码分析 三

列表类通用视图(list.py) 此文件包含用于显示数据列表常用的类和工具类.不仅可以方便的用于显示基于模型(Model)的数据列表,也可以用于显示自定义数据列表. 此图中绿色部分属于base.py,引入此图中是为了说明他们之间的关系 MultipleObjectMixin 最主要的核心工具类,主要的算法和接口全部都在这个工具类中实现. 属性 allow_empty 默认值True.表示没有数据时显示空列表:否则将会产生一个404错误. queryset 产生数据的queryset实例或"类qu

Django REST framework(基于类的视图CBV)

一丶基于类的视图 views.py下 from snippets.models import Snippet from snippets.serializers import SnippetSerializer from django.http import Http404 from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import

django:通用视图-UpdateView更新有参数的form类

这个提示放在开始:要想使用通用视图更新form,那么这个form的类型必须是ModelForm, 即: class FileForm(forms.ModelForm): .... 不要问我为什么知道的 ------------------------------------------------------------------------------------------------------ 首先:urls.py #coding=utf-8 from django.conf.urls

Django——基于类的视图源码分析 二

源码分析 抽象类和常用视图(base.py) 这个文件包含视图的顶级抽象类(View),基于模板的工具类(TemplateResponseMixin),模板视图(TemplateView)和重定向视图(RedirectView). View及View的执行顺序 View是所有基于类的视图的基类.仅实现了一些基本的方法和必要的检查工作.其中最重要的是dispatch方法.再次方法中,根据HTTP请求 中的method参数,调用相应的同名处理函数.这里留下了一个口子,后续的类需要根据自己的情况来填补

基于类的视图简介

使用基于类的视图 本质上,基于类的视图允许您使用不同的类实例方法响应不同的HTTP请求方法,而不是在单个视图函数中通过 if 逻辑来判断使用不同的代码来处理. 在视图函数中处理HTTP请求: from django.http import HttpResponse def my_view(request): if request.method == 'GET': # <view logic> return HttpResponse('result') 在基于类的视图中: from django

Django学习之通用视图(generic views)

Django的通用视图可以减少开发的单调性,它抽象出一些在视图开发中常用的代码和模式,这样就可以在无需编写大量代码的情况下,快速编写出常用的视图函数.下面将使用通用视图重写前面所写的代码.要使用通用视图,我们需要做几件事: 修改URLconf 编写基于通用视图的视图函数 1.修改URLconf from django.conf.urls import patterns,url from blog.views import * urlpatterns = patterns('', url(r'^$