Django-类视图

来源:互联网 发布:windows安装redis步骤 编辑:程序博客网 时间:2024/06/07 10:02

基于类的视图

视图是一个可调用对象,它接收一个请求然后返回一个响应。这个可调用对象不仅仅限于函数,Django 同时提供一些可以用作视图的类。它们允许你结构化你的视图并且利用继承和混合重用代码。后面我们将介绍一些用于简单任务的通用视图,但你可能想要设计自己的可重用视图的结构以适合你的使用场景。

基于类的内建通用视图

编写Web应用可能是单调的,因为你需要不断的重复某一种模式。 Django尝试从模型和模板层移除一些单调的情况,但是Web 开发者依然会在视图层经历这种厌烦。
Django的通用视图被开发用来消除这一痛苦。它们采用在视图开发过程中发现的某些共同的用法和模式然后把它们抽象出来,以便你能够写更少的代码快速的实现常见的视图。
我们能够识别一些基础的任务,比如展示对象的一个列表,以及编写代码来展示任何一个对象的列表。此外,涉及到的模型可以作为一个额外的参数传递到URLconf中。

扩展通用视图

如果你将你的视图实现为通用视图的子类,你就会发现这样能够更有效地编写你想要的代码,使用你自己的基于类或功能的视图。

对象的通用视图

TemplateView确实很有用,但是当你需要 呈现你数据库中的内容时Django的通用视图才真的会脱颖而出。因为这是如此常见的任务,Django 提供了一大把内置的通用视图,使生成对象的列表和详细视图变得极其容易。

注意:
当DjangoTemplates后端的APP_DIRS选项在TEMPLATES中设置为True时,模板的位置应该为:/path/to/project/books/templates/books/publisher_list.html

添加额外的上下文

你会经常需要展示一些通用视图不能提供的额外信息。 比如,考虑一下在每个Publisher 详细页面上显示一个包含所有图书的列表。那就需要DetailView,并且实现get_context_data方法
例如:

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

查看对象的子集

现在让我们来近距离查看下我们一直在用的model参数。model参数指定视图在哪个数据库模型之上进行操作,这适用于所有需要操作一个单独的对象或者一个对象集合的通用视图。然而,model参数并不是唯一能够指明视图要基于哪个对象进行操作的方法 —— 你同样可以使用queryset参数来指定一个对象列表:

from django.views.generic import DetailViewfrom books.models import Publisherclass PublisherDetail(DetailView):    context_object_name = 'publisher'    queryset = Publisher.objects.all()

指定model = Publisher等价于快速声明的queryset = Publisher.objects.all()。然而,通过使用queryset来定义一个过滤的对象列表,你可以更加详细 的了解哪些对象将会被显示在视图中(参见执行查询来获取更多关于查询集对象的更对信息,以及参见 基于类的视图参考来获取全部 细节)。
我们可能想要对图书列表按照出版日期进行排序来选择一个简单的例子,并且把 最近的放到前面:

from django.views.generic import ListViewfrom books.models import Bookclass BookList(ListView):    queryset = Book.objects.order_by('-publication_date')    context_object_name = 'book_list'

这是个非常简单的列子,但是它很好的诠释了处理思路。 当然,你通常想做的不仅仅只是对对象列表进行排序。如果你想要展现某个出版商的所有图书列表,你可以使用 同样的手法:

from django.views.generic import ListViewfrom books.models import Bookclass AcmeBookList(ListView):    context_object_name = 'book_list'    queryset = Book.objects.filter(publisher__name='Acme Publishing')    template_name = 'books/acme_list.html'

动态过滤

另一个普遍的需求是在给定的列表页面中根据URL中的关键字来过滤对象。 前面我们把出版 商的名字硬编码到URLconf中,但是如果我们想要编写一个视图来展示任何publisher的所有 图书,应该如何处理?
相当方便的是, ListView 有一个get_queryset() 方法来供我们重写。在之前,它只是返回一个queryset属性值,但是现在我们可以添加更多的逻辑。
让这种方式能够工作的关键点,在于当类视图被调用时,各种有用的对象被存储在self上;同request(self.request)一样,其中包含了从URLconf中获取到的位置参数 (self.args)和基于名字的参数(self.kwargs)(关键字参数)。
这里,我们拥有一个带有一组供捕获的参数的URLconf:

# urls.pyfrom django.conf.urls import urlfrom books.views import PublisherBookListurlpatterns = [    url(r'^books/([\w-]+)/$', PublisherBookList.as_view()),]

接着,我们编写了PublisherBookList视图:

# views.pyfrom django.shortcuts import get_object_or_404from django.views.generic import ListViewfrom books.models import Book, Publisherclass PublisherBookList(ListView):    template_name = 'books/books_by_publisher.html'    def get_queryset(self):        self.publisher = get_object_or_404(Publisher, name=self.args[0])        return Book.objects.filter(publisher=self.publisher)

执行额外的工作

使用基于类的视图处理表单

表单处理三个步骤:

  • 初始的GET (空白或预填充的表单)
  • 带有非法数据的POST(通常重新显示表单和错误信息)
  • 带有合法数据的POST(处理数据并重定向)

自己实现这些功能经常导致许多重复的样本代码(参见在视图中使用表单)。为了避免这点,Django 提供一系列的通用的基于类的视图用于表单的处理。

模型表单

通用的视图将自动创建一个ModelForm,只要它们能知道使用哪一个模型类:

  • 如果给出model 属性,则使用该模型类。
  • 如果get_object() 返回一个对象,则使用该对象的类。
  • 如果给出queryset,则使用该查询集的模型。
0 0
原创粉丝点击