django 1.8 官方文档翻译: 3-4-2 内建显示视图

Django 文档协作翻译小组人手紧缺,有兴趣的朋友可以加入我们,完全公益性质。

交流群:467338606

网站:http://python.usyiyi.cn/django/index.html

基于类的内建通用视图

编写Web应用可能是单调的,因为你需要不断的重复某一种模式。 Django尝试从model和 template层移除一些单调的情况,但是Web开发者依然会在view(视图)层经历这种厌烦。

Django的通用视图被开发用来消除这一痛苦。它们采用某些常见的习语和在开发过 程中发现的模式然后把它们抽象出来,以便你能够写更少的代码快速的实现基础的视图。

我们能够识别一些基础的任务,比如展示对象的列表,以及编写代码来展示任何对象的 列表。此外,有问题的模型可以作为一个额外的参数传递到URLconf中。

Django通过通用视图来完成下面一些功能:

  • 为单一的对象展示列表和一个详细页面。 如果我们创建一个应用来管理会议,那么 一个 TalkListView (讨论列表视图)和一个 RegisteredUserListView ( 注册用户列表视图)就是列表视图的一个例子。一个单独的讨论信息页面就是我们称 之为 “详细” 视图的例子。
  • 在年/月/日归档页面,以及详细页面和“最后发表”页面中,展示以数据库为基础的对象。
    允许用户创建,更新和删除对象 – 以授权或者无需授权的方式。

总的来说,这些视图提供了一些简单的接口来完成开发者遇到的大多数的常见任务。

扩展通用视图

使用通用视图可以极大的提高开发速度,是毫无疑问的。 然而在大多数工程中, 总会遇到通用视图无法满足需求的时候。的确,大多数来自Django开发新手 的问题是如何能使得通用视图的使用范围更广。

这是通用视图在1.3发布中被重新设计的原因之一 - 之前,它们仅仅是一些函数视图加上 一列令人疑惑的选项;现在,比起传递大量的配置到URLconf中,更推荐的扩展通用视图的 方法是子类化它们,并且重写它们的属性或者方法。

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

在一些三方的应用中,有更多通用视图的示例,或者你可以自己按需编写。

对象的通用视图

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

让我们来看一下这些通用视图中的”对象列表”视图。

我们将使用下面的模型:

# models.py
from django.db import modelsclass 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 __str__(self):              # __unicode__ on Python 2return self.nameclass Author(models.Model):salutation = models.CharField(max_length=10)name = models.CharField(max_length=200)email = models.EmailField()headshot = models.ImageField(upload_to='author_headshots')def __str__(self):              # __unicode__ on Python 2return self.nameclass Book(models.Model):title = models.CharField(max_length=100)authors = models.ManyToManyField('Author')publisher = models.ForeignKey(Publisher)publication_date = models.DateField()

现在我们需要定义一个视图:

# views.py
from django.views.generic import ListView
from books.models import Publisherclass PublisherList(ListView):model = Publisher

最后将视图解析到你的url上:

# urls.py
from django.conf.urls import url
from books.views import PublisherListurlpatterns = [url(r'^publishers/$', PublisherList.as_view()),
]

上面就是所有我们需要写的Python代码了。

注意

所以,当(例如)DjangoTemplates后端的APP_DIRS选项在TEMPLATES中设置为True时,模板的位置应该为:/path/to/project/books/templates/books/publisher_list.html。

这个模板将会依据于一个上下文(context)来渲染,这个context包含一个名为object_list 包含所有publisher对象的变量。一个非常简单的模板可能看起来像下面这样:

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

这确实就是全部代码了。 所有通用视图中有趣的特性来自于修改被传递到通用视图中的”信息” 字典。generic views reference文档详细 介绍了通用视图以及它的选项;本篇文档剩余的部分将会介绍自定义以及扩展通用 视图的常见方法。

编写“友好的”模板上下文

你可能已经注意到了,我们在publisher列表的例子中把所有的publisher对象 放到 object_list 变量中。虽然这能正常工作,但这对模板作者并不是 “友好的”。他们只需要知道在这里要处理publishers就行了。

因此,如果你在处理一个模型(model)对象,这对你来说已经足够了。 当你处理 一个object或者queryset时,Django能够使用你定义对象显示用的自述名(verbose name,或者复数的自述名,对于对象列表)来填充上下文(context)。提供添加到默认的 object_list 实体中,但是包含完全相同的数据,例如publisher_list。

如果自述名(或者复数的自述名) 仍然不能很好的符合要求,你 可以手动的设置上下文(context)变量的名字。在一个通用视图上的context_object_name属性指定了要使用的定了上下文变量:

# views.py
from django.views.generic import ListView
from books.models import Publisherclass PublisherList(ListView):model = Publishercontext_object_name = 'my_favorite_publishers'

提供一个有用的context_object_name总是个好主意。和你一起工作的设计 模板的同事会感谢你的。

添加额外的上下文

多数时候,你只是需要展示一些额外的信息而不是提供一些通用视图。 比如,考虑到每个publisher 详细页面上的图书列表的展示。DetailView通用视图提供了一个publisher对象给context,但是我们如何在模板中添加附加信息呢?

答案是派生DetailView,并且在get_context_data方法中提供你自己的实现。默认的实现只是简单的 给模板添加了要展示的对象,但是你这可以这样覆写来展示更多信息:

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

注意

通常来说,get_context_data会将当前类中的上下文数据,合并到所有超类中的上下文数据。要在你自己想要改变上下文的类中保持这一行为,你应该确保在超类中调用了get_context_data。如果没有任意两个类尝试定义相同的键,会返回异常的结果。然而,如果任何一个类尝试在超类持有一个键的情况下覆写它(在调用超类之后),这个类的任何子类都需要显式于超类之后设置它,如果你想要确保他们覆写了所有超类的话。如果你有这个麻烦,复查你视图中的方法调用顺序。

查看对象的子集

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

from django.views.generic import DetailView
from 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 ListView
from books.models import Bookclass BookList(ListView):queryset = Book.objects.order_by('-publication_date')context_object_name = 'book_list'

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

from django.views.generic import ListView
from 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'

注意,除了经过过滤之后的查询集,一起定义的还有我们自定义的模板名称。如果我们不这么做,通过视图会使用和 “vanilla” 对象列表名称一样的模板,这可 能不是我们想要的。

另外需要注意,这并不是处理特定出版商的图书的非常优雅的方法。 如果我们 要创建另外一个出版商页面,我们需要添加另外几行代码到URLconf中,并且再多几个 出版商就会觉得这么做不合理。我们会在下一个章节处理这个问题。

注意

如果你在访问 /books/acme/时出现404错误,检查确保你确实有一个名字为“ACME Publishing”的出版商。通用视图在这种情况下拥有一个allow_empty 的参数。详见基于类的视图参考。

动态过滤

另一个普遍的需求是在给定的列表页面中根据URL中的关键字来过滤对象。 前面我们把出版 商的名字硬编码到URLconf中,但是如果我们想要编写一个视图来展示任何publisher的所有 图书,应该如何处理?

相当方便的是, ListView 有一个get_queryset() 方法来供我们重写。在之前,它只是返回一个queryset属性值,但是现在我们可以添加更多的逻辑。

让这种方式能够工作的关键点,在于当类视图被调用时,各种有用的对象被存储在self上;同request()(self.request)一样,其中包含了从URLconf中获取到的位置参数 (self.args)和基于名字的参数(self.kwargs)(关键字参数)。

这里,我们拥有一个带有一组供捕获的参数的URLconf:

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

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

# views.py
from django.shortcuts import get_object_or_404
from django.views.generic import ListView
from 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)

如你所见,在queryset区域添加更多的逻辑非常容易;如果我们想的话,我们可以 使用self.request.user来过滤当前用户,或者添加其他更复杂的逻辑。

同时我们可以把出版商添加到上下文中,这样我们就可以在模板中使用它:

# ...def get_context_data(self, **kwargs):# Call the base implementation first to get a contextcontext = super(PublisherBookList, self).get_context_data(**kwargs)# Add in the publishercontext['publisher'] = self.publisherreturn context

执行额外的工作

我们需要考虑的最后的共同模式在调用通用视图之前或者之后会引起额外的开销。

想象一下,在我们的Author对象上有一个last_accessed字段,这个字段用来 跟踪某人最后一次查看了这个作者的时间。

# models.py
from django.db import models

class Author(models.Model):salutation = models.CharField(max_length=10)name = models.CharField(max_length=200)email = models.EmailField()headshot = models.ImageField(upload_to='author_headshots')last_accessed = models.DateTimeField()

通用的DetailView类,当然不知道关于这个字段的事情,但我们可以很容易 再次编写一个自定义的视图,来保持这个字段的更新。

首先,我们需要添加作者详情页的代码配置到URLconf中,指向自定义的视图:

from django.conf.urls import url
from books.views import AuthorDetailViewurlpatterns = [#...url(r'^authors/(?P<pk>[0-9]+)/$', AuthorDetailView.as_view(), name='author-detail'),
]

然后,编写我们新的视图 – get_object是用来获取对象的方法 – 因此我们简单的 重写它并封装调用:

from django.views.generic import DetailView
from django.utils import timezone
from books.models import Authorclass AuthorDetailView(DetailView):queryset = Author.objects.all()def get_object(self):# Call the superclassobject = super(AuthorDetailView, self).get_object()# Record the last accessed dateobject.last_accessed = timezone.now()object.save()# Return the objectreturn object

注意

这里URLconf使用参数组的名字pk - 这个名字是DetailView用来查找主键的值的默认名称,其中主键用于过滤查询集。

如果你想要调用参数组的其它方法,你可以在视图上设置pk_url_kwarg。详见 DetailView参考。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/263059.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

(原)学习ORACLE 视图

--视图--视图是一个逻辑表&#xff0c;是查看表的一种方式&#xff0c;用来定义来自一个或多个表的行和列的多种连接。通过视图&#xff0c;可以查看到表中的数据。--创建视图CREATE VIEW MYTEST.V_INFO(ID,NAME,LOGINNAME,Address)ASSELECT TEST.ID,TEST.NAME,TEST.LOGINNAME,…

记一次Hbase数据迁移和遇到的问题

因为集群不互通&#xff0c;所以采用手动方式迁移 1、下载目标集群数据 hadoop fs -get /apps/hbase/data/data/default/*c4be21d3000064c0 /mnt/data 2、远程复制数据&#xff0c;可以压缩一下 scp *** 3、上传数据到HDFS&#xff0c;一定要切换到hbase用户&#xff0c;不然会…

IIS中“使用 XSL 样式表无法查看 XML 输入”问题的解决

IIS中“使用 XSL 样式表无法查看 XML 输入”问题的解决2009-05-13 15:15今日安装IIS后&#xff0c;随便写了一个aspx的文件作为测试&#xff0c;发现浏览器中显示&#xff1a;使用 XSL 样式表无法查看 XML 输入。请更正错误然后单击 刷新按钮,或以后重试。这才发现了如下一个问…

SQL三种连接:内连接、外连接、交叉连接

SQL三种连接&#xff1a;内连接、外连接、交叉连接一、交叉连接&#xff08;CROSS JOIN&#xff09;二、内连接&#xff08;INNER JOIN&#xff09;三、外连接&#xff08;LEFT JOIN、RIGHT JOIN、FULL JOIN&#xff09;1.左外连接2.右外连接3.完整外连接准备两张表并以PersonI…

二叉树非递归先序遍历

二叉树的递归先序遍历很简单&#xff0c;假设二叉树的结点定义如下: 1 struct BinaryTreeNode 2 { 3 int m_nValue; 4 BinaryTreeNode* m_pLeft; 5 BinaryTreeNode* m_pRight; 6 }; 递归先序遵循:根-左-右的顺序 1 void PreOrder(BinaryTreeNode* Root) 2 { 3 …

面向对象与基于对象 区别

很多人没有区分“面向对象”和“基于对象”两个不同的概念。面向对象的三大特点&#xff08;封装&#xff0c;继承&#xff0c;多态&#xff09;却一不可。通常“基于对象”是使用对象&#xff0c;但是无法利用现有的对象模板产生新的对象类型&#xff0c;继而产生新的对象&…

Flex与Javascript交互

关键字&#xff1a;ExternalInterface 所用类库&#xff1a;SWFObject /** * Flex调用Javascript函数 * params functionName:String Javascript函数名称 * params ...params Javascript函数参数 * return 返回Javascript函数的return内容 **/ ExternalInterface.call(…

显示器调校与Soft Proofing ZZ

版权归原作者所有&#xff01; http://www.cgan.net/science/popular/cookie/displayregulate.htm 自从桌面出版走到计算机上&#xff0c;显示器成为印前流程中重要的设备之一。从扫描、数码摄影、相片修改、排版等工序中&#xff0c;也可找到显示器的存在。但往往很多同业却忽…

SparkContext: Error initializing SparkContext解决方法

SparkContext: Error initializing SparkContext解决方法Spark在配置高可用集群中&#xff0c;出现报错 ERROR SparkContext: Error initializing SparkContext. java.net.ConnectException: Call From hadoop102/192.168.10.102 to hadoop102:8020 failed on connection excep…

tomcat 绑定 ip 及域名,限制非法域名访问

公司WEB 采用linuxtomcat架构。经常会收到电信的警告&#xff0c;说某个IP下挂用了未备案域名&#xff0c;如果不处理就封IP。鉴于此&#xff0c;需要将tomcat的访问地址进行限制&#xff0c;只允许通过IP地址或者自己指定的域名来访问。配置tomcat/conf/server.xml 文件&#…

数据库设计(四)概念数据模型

目标&#xff1a;本文主要介绍如何定义实体的主、次标识符。一、标识符标识符是实体中一个或多个属性的集合&#xff0c;可用来唯一标识实体中的一个实例。要强调的是&#xff0c;CDM中的标识符等价于PDM中的主键或候选键。每个实体都必须至少有一个标识符。如果实体只有一个标…

error C2471和error C1083

error C2471和error C1083 VS2008IDE&#xff1a;编译时出现问题&#xff1a;error C2471: 无法更新程序数据库“d:\my documents\visual studio 2008\projects\mdib\mdib\debug\vc90.pdb”error C1083: 无法打开程序数据库文件:“d:\my documents\visual studio 2008\projects…

中文/英文换行总结

html部分 <div class"parent"><p class"p1">湿哒哒大的大大大的大的大大大的大的啊啊大大大啊大大打啊打大大大</p><p class"p2">湿哒哒大的大大大的大的大大大的大的啊啊大大大啊大大打啊打大大大</p><p clas…

Go学习笔记—基于Go的进程间通信

IPC&#xff08;Inter-Process Communication 进程间通信&#xff09; 一般方法&#xff1a;(1) 半双工Unix管道 (2) FIFOs(命名管道) (3) 消息队列 (4) 信号量 (5) 共享内存 (6) 网络Socket (7) RPC(远程过程调用) &#xff08;一&#xff09;管道&#xff08;Pipe&#xff…

rsync+lsyncd实现(本地以及远程)文件实时同步

lsyncd基于lua语言开发&#xff0c;整合了rsync和notify 实现文件的实时同步 系统环境cat /etc/issue CentOS release 6.6 (Final)uname -sr Linux 2.6.32-504.el6.x86_64 服务器规划 rsync服务器&#xff1a; 192.168.10.241 rsync lsyncd服务器 &#xff…

萨蒂扬软件技术(南京)研发中心”落户高新区

萨蒂扬软件技术&#xff08;南京&#xff09;研发中心”落户高新区 2007-02-12“中国软件名城”成为南京吸引世界软件巨头强磁场“萨蒂扬软件技术&#xff08;南京&#xff09;研发中心”落户高新区 世界知名的印度软件企业巨头萨帝扬计算机服务有限公司挥师江苏亮出精彩第一笔…

JavaScript常用正则表达式收集

JavaScript常用正则表达式收集 ---------------------------------------------------------------------------------------- 正则的用法参见&#xff1a;http://blog.csdn.net/xxj_jing/article/details/6977078 下面是个简单判断 1.匹配中文字符 2.匹配特殊字符(符合 wind…

Go学习笔记—多线程

多线程编程 ​ 一个进程可以包含多个线程&#xff0c;这些线程运行的一定是同一个程序&#xff08;进程程序&#xff09;&#xff0c;且都由当前进程中已经存在的线程通过系统调用的方式创建出来。进程是资源分配的基本单位&#xff0c;线程是调度运行的基本单位&#xff0c;线…

maven必知必会

目录 了解mavenmaven的作用maven仓库本地配置添加远程仓库依赖搜索顺序定制包到本地仓库pom文件依赖管理原则构建声明周期插件了解maven maven的作用 maven采取约定大于配置的原则,规范了一套标准的javaweb项目结构maven提供了完备的包管理功能,不用到处找jar包了maven提供了一…

lecture 4 : More Objective-C

Creating Objects 这件事困扰我一点时间了&#xff0c;ObjC没有一个Constructor的概念 而在Create Objects这件事上既有用过自己写的-init&#xff0c;还return instancetype&#xff0c;大概这个&#xff0c;也有用过一些Class Method&#xff0c;就是明确知道是id类型的&…