第11章 通用视图

freedoom 05-23 06:52

没有细致看,不过django 已经更新成使用 class-based generic view 了,参考 https://docs.djangoproject.com/en/1.4/topics/class-based-views/

lincy 08-22 00:54

按官网,本章实际应该叫《基于类的通用视图》,因为本章实在是让人难以忍受,我特意花了不少时间去官网看了这部分,实际上是分为4块,我翻译总结在我的博客http://www.cnblogs.com/huafeng/,有需要的可以看一下

zzm88 09-18 05:20

ls真是大好人!!!

njw 12-24 09:07

https://docs.djangoproject.com/en/dev/topics/class-based-views/

July 03-27 13:24

对照 1.6 的文档看了一下2楼的博客,不得不说翻译的比较糟糕...

现在用class-based generic view 了唉 07-28 03:48

mihello 09-07 11:36

这一章严重过时,参考 Django 1.6 基于类的通用试图 http://www.pythontip.com/blog/post/12172/ 官方文档 https://docs.djangoproject.com/en/dev/ref/class-based-views http://django-14-tkliuxing.readthedocs.org/en/latest/topics/class-based-views.html 这三个链接,下面各位道友的评论有提及到

mihello 09-08 14:12

@lincy 太棒了

URMyFaith 09-20 17:52

https://github.com/urmyfaith/NotesOfDjangoBook/blob/master/notes/2014-09-20-Notes-of-Django-Boook-Chapter11-generic_view.md 每个都具体实现了

对标题的评论会显示在这里

这里需要再次回到本书的主题: 在最坏的情况下, Web 开发是一项无聊而且单调的工作。 到目前为止,我们已经介绍了 Django 怎样在模型和模板的层面上减小开发的单调性,但是 Web 开发在视图的层面上,也经历着这种令人厌倦的事情。

对这一段的评论会显示在这里

Django的通用视图 可以减少这些痛苦。 它抽象出一些在视图开发中常用的代码和模式,这样就可以在无需编写大量代码的情况下,快速编写出常用的数据视图。 事实上,前面章节中的几乎所有视图的示例都可以在通用视图的帮助下重写。

对这一段的评论会显示在这里

在第八章简单的向大家介绍了怎样使视图更加的“通用”。 回顾一下,我们会发现一些比较常见的任务,比如显示一系列对象,写一段代码来显示 任何 对象内容。 解决办法就是传递一个额外的参数到URLConf。

对这一段的评论会显示在这里

Django内建通用视图可以实现如下功能:

对这一段的评论会显示在这里
  • 完成常用的简单任务: 重定向到另一个页面以及渲染一个指定的模板。
  • 显示列表和某个特定对象的详细内容页面。 第8章中提到的 event_listentry_list 视图就是列表视图的一个例子。 一个单一的 event 页面就是我们所说的详细内容页面。
  • 呈现基于日期的数据的年/月/日归档页面,关联的详情页面,最新页面。 Django Weblogs (http://www.djangoproject.com/weblog/)的年、月、日的归档就是使用通用视图 架构的,就像是典型的新闻报纸归档。
对这一段的评论会显示在这里

综上所述,这些视图为开发者日常开发中常见的任务提供了易用的接口。

对这一段的评论会显示在这里

使用通用视图

ode2free 05-10 19:30

通用视图在django 1.3中的变化:http://docs.djangoproject.com/en/dev/topics/generic-views-migration/

melzg 03-25 13:31

按楼上提示,做了如下替换,还是不行。 //错误:Django Version: 1.3.1 Exception Type: TemplateDoesNotExist Exception Value: about.html // To do this, replace the reference to the generic view function with a as_view() instantiation of the class-based view. For example, the old-style direct_to_template pattern: ('^about/$', direct_to_template, {'template': 'about.html'}) can be replaced with an instance of TemplateView: ('^about/$', TemplateView.as_view(template_name='about.html'))

timest.lyy@gmail.com 03-27 07:09

from django.views.generic.base import TemplateView urlpatterns = patterns('', (r'^about/$', TemplateView.as_view(template_name='about.html')) try this !

weetao 05-20 16:00

是不是还是要自己写about.html?

Brilliant 06-28 07:19

对,要写的,generic view让你少写一个views

Maxint64 04-18 03:44

direct_to_template在Django1.5中不能使用,替代方案:http://stackoverflow.com/questions/15117835/django-1-5-index-page

guwb 05-25 07:34

感谢ls提供的链接

同谢 06-25 09:13

njw 08-16 07:33

direct_to_template 在django 1.5已经不存在了,改成以下语句: from django.views.generic import TemplateView urlpatterns = patterns('', (r'^$', TemplateView.as_view(template_name="about.html")), )

njw 08-16 07:33

urlpatterns = patterns('', (r'^about/$', TemplateView.as_view(template_name="about.html")), ) )

楼上正解。 07-28 03:36

Mellcap 08-14 10:30

Thanks for @timest.lyy@gmail.com

test 10-19 03:31

对这一段的评论会显示在这里

使用通用视图的方法是在URLconf文件中创建配置字典,然后把这些字典作为URLconf元组的第三个成员。 (对于这个技巧的应用可以参看第八章向视图传递额外选项。)

对这一段的评论会显示在这里

例如,下面是一个呈现静态“关于”页面的URLconf:

对这一段的评论会显示在这里
from django.conf.urls.defaults import *
from django.views.generic.simple import direct_to_template

urlpatterns = patterns('',
    (r'^about/$', direct_to_template, {
        'template': 'about.html'
    })
)
对这一段的评论会显示在这里

一眼看上去似乎有点不可思议,不需要编写代码的视图! 它和第八章中的例子完全一样:direct_to_template视图仅仅是直接从传递过来的额外参数获取信息并用于渲染视图。

对这一段的评论会显示在这里

因为通用视图都是标准的视图函数,我们可以在我们自己的视图中重用它。 例如,我们扩展 about例子,把映射的URL从 /about//修改到一个静态渲染 about/.html 。 我们首先修改URL配置以指向新的视图函数:

wgzhao 05-20 11:02

<whatever>.html 这里的<whatever>不能省略(估计是当作tag解析了),否则看上去有歧义了。

bai 01-29 13:22

about/.html 应为about.html

对这一段的评论会显示在这里
from django.conf.urls.defaults import *
from django.views.generic.simple import direct_to_template
**from mysite.books.views import about_pages**

urlpatterns = patterns('',
    (r'^about/$', direct_to_template, {
        'template': 'about.html'
    }),
    **(r'^about/(\w+)/$', about_pages),**
)
weetao 05-20 18:50

1.4:urls.py: from django.views.generic.base import TemplateView urlpatterns = patterns('', url(r'^about/(\w+)/$',views.about_pages.as_view()), ) views.py: from django.views.generic.base import TemplateView class about_pages(TemplateView): def get_template_names(self): return 'about/%s.html' % self.args[0]

匿名读者 04-25 03:04

Django1.5.5和Django1.6都已弃用simple这个模块。 改成: from django.conf.urls import patterns from django.views.generic import TemplateView urlpatterns = patterns(’’, (r’^about/’, TemplateView.as_view(template_name="about.html")), )

对这一段的评论会显示在这里

接下来,我们编写 about_pages 视图的代码:

对这一段的评论会显示在这里
from django.http import Http404
from django.template import TemplateDoesNotExist
from django.views.generic.simple import direct_to_template

def about_pages(request, page):
    try:
        return direct_to_template(request, template="about/%s.html" % page)
    except TemplateDoesNotExist:
        raise Http404()
小利子 01-14 15:20

No module named simple 我的django版本是1.5的

小利子 01-14 15:28

from django.views.generic import TemplateView 将direct_to_template换成return TemplateView.as_view(request,template='about/%s.html'%page)

helloworld 05-05 09:44

as_view只能接受一个参数。

helloworld 05-05 10:13

1.5的通用视图不是这么玩的了。https://docs.djangoproject.com/en/1.5/ref/class-based-views/base/#django.views.generic.base.View.dispatch

greeb 05-11 16:22

我的跟小利子的问题一样,按小利子的方法改了还是不行

mstools 09-13 03:27

def about_page(request, page): return render_to_response("about/%s.html" %page) 这里直接用一个render_to_response也能解决问题,为什么要用这个还是没有明白.

tommy 11-19 08:08

我使用templateView.as_view(template_name='about/%s.html'%page)后,界面上报错:'function' object has no attribute 'get'?这是为啥?

harvey 05-12 13:14

http://pythontip.sinaapp.com/blog/post/12172/ Django 1.6 基于类的通用视图

angel 11-22 08:13

确实没有必要在视图函数里用TempalteView,直接用render_to_response( )就可以了,何必要这么麻烦

horizonshd 09-20 01:31

在Django-1.11.3中,【from django.template.exceptions import TemplateDoesNotExist】 【from django.views.generic import TemplateView】

horizonshd 09-20 02:00

在Django-1.11.3中,错误【'function' object has no attribute 'get'】的一种解决方式:【return TemplateView.as_view(template_name="about/%s.html"%page)(request)】

对这一段的评论会显示在这里

在这里我们象使用其他函数一样使用 direct_to_template 。 因为它返回一个HttpResponse对象,我们只需要简单的返回它就好了。 这里唯一有点棘手的事情是要处理找不到模板的情况。 我们不希望一个不存在的模板导致一个服务端错误,所以我们捕获TemplateDoesNotExist异常并且返回404错误来作为替代。

walker 03-29 05:47

对这一段的评论会显示在这里

这里有没有安全性问题?

对这一段的评论会显示在这里

眼尖的读者可能已经注意到一个可能的安全漏洞: 我们直接使用从客户端浏览器得到的数据构造模板名称(template="about/%s.html" % page )。乍看起来,这像是一个经典的 目录跨越(directory traversal) 攻击(详情请看第20章)。 事实真是这样吗?

对这一段的评论会显示在这里

完全不是。 是的,一个恶意的 page 值可以导致目录跨越,但是尽管 page 从请求的URL中获取的,但并不是所有的值都会被接受。 这就是URL配置的关键所在: 我们使用正则表达式 \w+ 来从URL里匹配 page ,而 \w 只接受字符和数字。 因此,任何恶意的字符 (例如在这里是点 . 和正斜线 / )将在URL解析时被拒绝,根本不会传递给视图函数。

生命至上 10-10 06:55

前几章时也有说过类似的值检验问题

iizax 04-26 02:15

那个是XSS攻击,有点区别。

对这一段的评论会显示在这里

对象的通用视图

对这一段的评论会显示在这里

direct_to_template 毫无疑问是非常有用的,但Django通用视图最有用的地方是呈现数据库中的数据。 因为这个应用实在太普遍了,Django带有很多内建的通用视图来帮助你很容易 地生成对象的列表和明细视图。

对这一段的评论会显示在这里

让我们先看看其中的一个通用视图: 对象列表视图。 我们使用第五章中的 Publisher 来举例:

对这一段的评论会显示在这里
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()

    def __unicode__(self):
        return self.name

    class Meta:
        ordering = ['name']
zlleah 01-21 03:06

第五章:class Meta,内嵌于 Publisher 这个类的定义中(如果 class Publisher 是顶格的,那么 class Meta 在它之下要缩进4个空格--按 Python 的传统 )。你可以在任意一个 模型 类中使用 Meta 类,来设置一些与特定模型相关的选项。 在 附录B 中有 Meta 中所有可选项的完整参考,现在,我们关注 ordering 这个选项就够了。 如果你设置了这个选项,那么除非你检索时特意额外地使用了 order_by(),否则,当你使用 Django 的数据库 API 去检索时,Publisher对象的相关返回值默认地都会按 name 字段排序。

Django Chu 06-26 14:21

ls真贴心~

atlas 10-05 06:42

1s 真贴心+1

DjangoLearner 01-10 15:32

顶LSS!

对这一段的评论会显示在这里

要为所有的出版商创建一个列表页面,我们使用下面的URL配置:

对这一段的评论会显示在这里
from django.conf.urls.defaults import *
from django.views.generic import list_detail
from mysite.books.models import Publisher

publisher_info = {
    'queryset': Publisher.objects.all(),
}

urlpatterns = patterns('',
    (r'^publishers/$', list_detail.object_list, publisher_info)
)
melzg 03-25 14:52

1.3.1版本中,这么来用:(r'^publishers/$', list.ListView.as_view(model=Publisher, template_name='publisher_list_page.html')),

melzg 03-25 16:01

1.3.1版本中,有很多不同了,这部分例子的内容,已经都跟不上了。

Rex 07-09 12:50

难怪感觉此章节内容蹩脚,新版的代码果然更加省事!

winkidney 06-06 07:05

在https://docs.djangoproject.com/en/1.5/topics/class-based-views/generic-display/ 这个网页的例子中,那个模板指定 的方式应该是 url(r'^publishers/$',PublisherList.as_view(template_name='books/publisher_list.html')),别的照着网页代码即可。ls提供的代码将urls和model交叉混合了,这个老的例子非常不合理

对这一段的评论会显示在这里

这就是所要编写的所有Python代码。 当然,我们还需要编写一个模板。 我们可以通过在额外参数字典中包含一个template_name键来显式地告诉object_list视图使用哪个模板:

对这一段的评论会显示在这里
from django.conf.urls.defaults import *
from django.views.generic import list_detail
from mysite.books.models import Publisher

publisher_info = {
    'queryset': Publisher.objects.all(),
    **'template_name': 'publisher_list_page.html',**
}

urlpatterns = patterns('',
    (r'^publishers/$', list_detail.object_list, publisher_info)
)
vincent 05-06 08:45

这属于硬编码吧?感觉这样不太舒服。

smallcat 10-23 13:41

在通用试图中一会儿使用template作为模板名称,一会儿使用template_name作为模板名称,这样的命名方式是否需要得到改进呢?

xiaocainiaok 04-30 08:03

list_detail.object_list 我怎么知道 类似这样的模板 需要什么 字典参数?

zlleah 01-21 04:56

@xiaocainiaok ,你可以进入django.views.generic.list_detail.object_list 查看

athos 03-18 15:31

from django.views.generic import list_detail 报错: ImportError: cannot import name list_detail,我用的是1.5版本,这个模块改成哪个了?

dkjiaoyang 04-17 00:22

回楼上,1.5是django.views.generic.list.ListView

dkjiaoyang 04-17 00:25

回楼上上,list_detail.object_detail 也变成了 ListView.as_view()

匿名读者 04-27 14:48

django 1.5 里头改的很多 包括urls还有views 大家参考:https://docs.djangoproject.com/en/1.5/topics/class-based-views/generic-display/

s 04-27 14:49

django 1.5 里头改的很多 包括urls还有views 大家参考:https://docs.djangoproject.com/en/1.5/topics/class-based-views/generic-display/

atlas 10-05 07:25

真心的要看楼上提供的链接,django 1.5的简单很多很多

大耳 11-23 02:52

把字典里的元素传递给函数做参数,直接放入函数并且在前面加上** url(r'^$',ListView.as_view(**publisher_info)),

大耳 11-23 03:06

这块看我的笔记 https://app.yinxiang.com/shard/s22/sh/3fa3602b-769d-47c3-b02a-31abecc2f208/365a03873baf0d7875547ca1e417b152

ifaint 01-04 16:08

ls,印象笔记已经不能分享链接了

对这一段的评论会显示在这里

在缺少template_name的情况下,object_list通用视图将自动使用一个对象名称。 在这个例子中,这个推导出的模板名称将是 "books/publisher_list.html" ,其中books部分是定义这个模型的app的名称, publisher部分是这个模型名称的小写。

对这一段的评论会显示在这里

这个模板将按照 context 中包含的变量 object_list 来渲染,这个变量包含所有的书籍对象。 一个非常简单的模板看起来象下面这样:

chickwood 05-19 01:49

"包含所有的书籍对象" -> "包含所有的出版商对象"

skywind 05-09 03:35

说白了就是省了一个view的函数。

horizonshd 09-21 06:59

楼上说的对

horizonshd 09-21 07:59

【ListView.as_view()】是怎么把对应的结果集放在变量【object_list】中的啊?是在哪儿设置的?

imbaqian 07-06 07:54

这样写的好处是什么呢? 感觉写View更整齐统一...

对这一段的评论会显示在这里
{% extends "base.html" %}

{% block content %}
    <h2>Publishers</h2>
    <ul>
        {% for publisher in object_list %}
            <li>{{ publisher.name }}</li>
        {% endfor %}
    </ul>
{% endblock %}
对这一段的评论会显示在这里

(注意,这里我们假定存在一个base.html模板,它和我们第四章中的一样。)

对这一段的评论会显示在这里

这就是所有要做的事。 要使用通用视图酷酷的特性只需要修改参数字典并传递给通用视图函数。 附录D是通用视图的完全参考资料;本章接下来的章节将讲到自定义和扩展通用视图的一些方法。

对这一段的评论会显示在这里

扩展通用视图

对这一段的评论会显示在这里

毫无疑问,使用通用视图可以充分加快开发速度。 然而,在多数的工程中,也会出现通用视图不能 满足需求的情况。 实际上,刚接触Django的开发者最常见的问题就是怎样使用通用视图来处理更多的情况。

对这一段的评论会显示在这里

幸运的是,几乎每种情况都有相应的方法来简易地扩展通用视图以处理这些情况。 这时总是使用下面的 这些方法。

对这一段的评论会显示在这里

制作友好的模板Context

对这一段的评论会显示在这里

你也许已经注意到范例中的出版商列表模板在变量 object_list 里保存所有的书籍。这个方法工作的很好,只是对编写模板的人不太友好。 他们必须知道这里正在处理的是书籍。 更好的变量名应该是publisher_list,这样变量所代表的内容就显而易见了。

chickwood 05-19 01:51

"保存所有的书籍" -> "保存所有的出版商" "正在处理的是书籍" -> "正在处理的是出版商"

对这一段的评论会显示在这里

我们可以很容易地像下面这样修改 template_object_name 参数的名称:

chickwood 05-19 01:58

我们可以很容易地利用 template_object_name 参数来修改这个变量名:

Gothack 11-10 06:54

我在用extra_context的时候遇到password_change() got an unexpected keyword argument 'queryset' 这个怎么解决

对这一段的评论会显示在这里
from django.conf.urls.defaults import *
from django.views.generic import list_detail
from mysite.books.models import Publisher

publisher_info = {
    'queryset': Publisher.objects.all(),
    'template_name': 'publisher_list_page.html',
    'template_object_name': 'publisher',
}

urlpatterns = patterns('',
    (r'^publishers/$', list_detail.object_list, publisher_info)
)
对这一段的评论会显示在这里

在模板中,通用视图会通过在template_object_name后追加一个_list的方式来创建一个表示列表项目的变量名。

(^_^) 04-01 14:15

如上例所示,那么在模板文件 publisher_list_page.html 里,可以用(在template_object_name值的后面加_list,如) publisher_list 的写法,来代替 object_list。

chickwood 05-19 02:04

-> "通用视图会...的变量名,在模板中则应该使用这个变量名(代替原来的object_list)。"

silent 11-05 12:19

如果在publisher_info使用了template_object_name,并且值设为publisher,则在编写模板的时候不能够使用object_list作为传入列表对象的变量名,而应该使用publisher_list。如果使用object_list作为传入列表的变量名,那么模板收不到该变量,会显示为空。

jwfy 03-01 13:22

在django 1.5版本中 好像是使用 context_object_name 详见:https://docs.djangoproject.com/en/1.5/topics/class-based-views/generic-display/

mr.liu 09-14 09:13

1.5后使用'context_object_name':'publisher',并且使用变量时候,不需要再后面追加_list

对这一段的评论会显示在这里

使用有用的 template_object_name 总是个好想法。 你的设计模板的合作伙伴会感谢你的。

对这一段的评论会显示在这里

添加额外的Context

horizonshd 09-21 08:16

在Django-1.11.3中,以下的部分准备不看了

对这一段的评论会显示在这里

你常常需要呈现比通用视图提供的更多的额外信息。 例如,考虑一下在每个出版商的详细页面显示所有其他出版商列表。 object_detail 通用视图为context提供了出版商信息,但是看起来没有办法在模板中 获取 所有 出版商列表。

C墨 10-03 06:03

“例如,考虑一下在每个出版商的详细页面显示所有其他出版商列表。”为什么 下面传入的是书籍列表呢? **'extra_context': {'book_list': Book.objects.all()}**

峰哥 09-17 03:33

应该是显示该出版商的所有书籍

mr.liu 09-14 09:15

这越到后面,看着翻译好头疼。

对这一段的评论会显示在这里

这是解决方法: 所有的通用视图都有一个额外的可选参数 extra_context 。这个参数是一个字典数据类型,包含要添加到模板的context中的额外的对象。 所以要给视图提供所有出版商的列表,我们就用这样的info字典:

对这一段的评论会显示在这里
publisher_info = {
    'queryset': Publisher.objects.all(),
    'template_object_name': 'publisher',
    **'extra_context': {'book_list': Book.objects.all()}**
}
rainie 02-19 08:08

'template_name': 'publisher_list_page.html', 请问这一行是可以省略的么,省略不是找不到url到模板的对应关系了?

jwfy 03-01 13:26

get_context_data

匿名读者 10-30 08:05

按照下面的说法,book.objects.all()应该木有括弧啊

mr.liu 09-14 09:36

extra_context 这个替换成什么了???

对这一段的评论会显示在这里

这样就把一个 {{ book_list }} 变量放到模板的context中。 这个方法可以用来传递任意数据 到通用视图模板中去,非常方便。 这是非常方便的

对这一段的评论会显示在这里

不过,这里有一个很隐蔽的BUG,不知道你发现了没有?

对这一段的评论会显示在这里

我们现在来看一下, extra_context 里包含数据库查询的问题。 因为在这个例子中,我们把 Publisher.objects.all() 放在URLconf中,它只会执行一次(当URLconf第一次加载的时候)。 当你添加或删除出版商,你会发现在重启Web服务器之前,通用视图不会反映出这些修改(有关QuerySet何时被缓存和赋值的更多信息请参考附录C中“缓存与查询集”一节)。

董海 03-05 03:12

原文提示好像不太一致,我理解是:如果你对Publisher进行了更改,Book.objects.all()的数据不会被刷新,对于Publisher.objects.all()的数据django不会缓存. The problem has to do with when the queries in extra_context are evaluated. Because this example puts Book.objects.all() in the URLconf, it will be evaluated only once (when the URLconf is first loaded). Once you add or remove publishers, you’ll notice that the generic view doesn’t reflect those changes until you reload the Web server (see “Caching and QuerySets” in Appendix C for more information about when QuerySet objects are cached and evaluated).

董海 03-05 03:13

原文提示好像不太一致,我理解是:如果你对Publisher进行了更改,Book.objects.all()的数据不会被刷新,对于Publisher.objects.all()的数据django不会缓存.备注有说明. The problem has to do with when the queries in extra_context are evaluated. Because this example puts Book.objects.all() in the URLconf, it will be evaluated only once (when the URLconf is first loaded). Once you add or remove publishers, you’ll notice that the generic view doesn’t reflect those changes until you reload the Web server (see “Caching and QuerySets” in Appendix C for more information about when QuerySet objects are cached and evaluated).

vayn 03-06 15:51

没错,这块完全搞错了。原文是Because this example puts Book.objects.all() in the URLconf, it will be evaluated only once。是Book.objects.all(),不是Publisher.objects.all()

Wing shine 11-29 10:24

Publisher.objects.all() ---->Book.objects.all()

对这一段的评论会显示在这里

备注

对这一段的评论会显示在这里

这个问题不适用于通用视图的 queryset 参数。 因为Django知道有些特别的 QuerySet 永远不能 被缓存,通用视图在渲染前都做了缓存清除工作。

对这一段的评论会显示在这里

解决这个问题的办法是在 extra_context 中用一个回调(callback)来代替使用一个变量。 任何传递给extra_context的可调用对象(例如一个函数)都会在每次视图渲染前执行(而不是只执行一次)。 你可以象这样定义一个函数:

vayn 03-06 15:52

也就是在 extra_context 中用 callback 代替 Book.objects.all()

对这一段的评论会显示在这里
**def get_books():**
    **return Book.objects.all()**

publisher_info = {
    'queryset': Publisher.objects.all(),
    'template_object_name': 'publisher',
    'extra_context': **{'book_list': get_books}**
}
对这一段的评论会显示在这里

或者你可以使用另一个不是那么清晰但是很简短的方法,事实上 Publisher.objects.all 本身就是可以调用的:

vayn 03-06 15:58

又错了!是 Book.objects.all(),不是Publisher.objects.all()

luxi78 04-12 16:33

如何修复错误? 这里的翻译太随意了,初学者很容易看迷糊并被误导得想入非非的

jwfy 03-01 13:30

淡定点,有错这是难免的,知道就指出来,让后来的人看到就行了 这里和1.5的版本确实有很多发生变化,建议看看:https://docs.djangoproject.com/en/1.5/topics/class-based-views/generic-display/

对这一段的评论会显示在这里
publisher_info = {
    'queryset': Publisher.objects.all(),
    'template_object_name': 'publisher',
    'extra_context': **{'book_list': Book.objects.all}**
}
对这一段的评论会显示在这里

注意 Book.objects.all 后面没有括号;这表示这是一个函数的引用,并没有真正调用它(通用视图将会在渲染时调用它)。

对这一段的评论会显示在这里

显示对象的子集

对这一段的评论会显示在这里

现在让我们来仔细看看这个 queryset 。 大多数通用视图有一个queryset参数,这个参数告诉视图要显示对象的集合 (有关QuerySet的解释请看第五章的 “选择对象”章节,详细资料请参看附录B)。

对这一段的评论会显示在这里

举一个简单的例子,我们打算对书籍列表按出版日期排序,最近的排在最前:

对这一段的评论会显示在这里
book_info = {
    'queryset': Book.objects.order_by('-publication_date'),
}

urlpatterns = patterns('',
    (r'^publishers/$', list_detail.object_list, publisher_info),
    **(r'^books/$', list_detail.object_list, book_info),**
)
12-13 05:57

此处只objects.order_by而不objects.all么?

对这一段的评论会显示在这里

这是一个相当简单的例子,但是很说明问题。 当然,你通常还想做比重新排序更多的事。 如果你想要呈现某个特定出版商出版的所有书籍列表,你可以使用同样的技术:

对这一段的评论会显示在这里
**apress_books = {**
    **'queryset': Book.objects.filter(publisher__name='Apress Publishing'),**
    **'template_name': 'books/apress_list.html'**
**}**

urlpatterns = patterns('',
    (r'^publishers/$', list_detail.object_list, publisher_info),
    **(r'^books/apress/$', list_detail.object_list, apress_books),**
)
zlleah 01-21 05:29

按照之前给的Book模型,应该为publisher,而不是publisher_name

leejaen 05-03 11:02

ls,这里没有错,写的是publisher__name

对这一段的评论会显示在这里

注意 在使用一个过滤的 queryset 的同时,我们还使用了一个自定义的模板名称。 如果我们不这么做,通用视图就会用以前的模板,这可能不是我们想要的结果。

对这一段的评论会显示在这里

同样要注意的是这并不是一个处理出版商相关书籍的最好方法。 如果我们想要添加另一个 出版商页面,我们就得在URL配置中写URL配置,如果有很多的出版商,这个方法就不能 接受了。 在接下来的章节我们将来解决这个问题。

宾临城下 06-04 02:54

我们就得在URL配置中写URL配置 ---> 我们就得在URL配置中写另一个版商对应的URL

对这一段的评论会显示在这里

用函数包装来处理复杂的数据过滤

对这一段的评论会显示在这里

另一个常见的需求是按URL里的关键字来过滤数据对象。 之前,我们在URLconf中硬编码了出版商的名字,但是如果我们想用一个视图就显示某个任意指定的出版商的所有书籍,那该怎么办呢? 我们可以通过对 object_list 通用视图进行包装来避免 写一大堆的手工代码。 按惯例,我们先从写URL配置开始:

对这一段的评论会显示在这里
urlpatterns = patterns('',
    (r'^publishers/$', list_detail.object_list, publisher_info),
    **(r'^books/(\w+)/$', books_by_publisher),**
)
对这一段的评论会显示在这里

接下来,我们写 books_by_publisher 这个视图:

对这一段的评论会显示在这里
from django.shortcuts import get_object_or_404
from django.views.generic import list_detail
from mysite.books.models import Book, Publisher

def books_by_publisher(request, name):

    # Look up the publisher (and raise a 404 if it can't be found).
    publisher = get_object_or_404(Publisher, name__iexact=name)

    # Use the object_list view for the heavy lifting.
    return list_detail.object_list(
        request,
        queryset = Book.objects.filter(publisher=publisher),
        template_name = 'books/books_by_publisher.html',
        template_object_name = 'book',
        extra_context = {'publisher': publisher}
    )
Rex 07-09 12:03

这段代码,从编码量上来说,使用render_to_response似乎会来得更简洁。 暂时无法体会通用视图的妙处,感觉过度包装了。

对这一段的评论会显示在这里

这样写没问题,因为通用视图就是Python函数。 和其他的视图函数一样,通用视图也是接受一些 参数并返回 HttpResponse 对象。 因此,通过包装通用视图函数可以做更多的事。

对这一段的评论会显示在这里

注意

对这一段的评论会显示在这里

注意在前面这个例子中我们在 extra_context中传递了当前出版商这个参数。

对这一段的评论会显示在这里

处理额外工作

对这一段的评论会显示在这里

我们再来看看最后一个常用模式:

对这一段的评论会显示在这里

想象一下我们在 Author 对象里有一个 last_accessed 字段,我们用这个字段来记录最近一次对author的访问。 当然通用视图 object_detail 并不能处理这个问题,但是我们仍然可以很容易地编写一个自定义的视图来更新这个字段。

对这一段的评论会显示在这里

首先,我们需要在URL配置里设置指向到新的自定义视图:

对这一段的评论会显示在这里
from mysite.books.views import author_detail

urlpatterns = patterns('',
    # ...
    **(r'^authors/(?P<author_id>\d+)/$', author_detail),**
    # ...
)
对这一段的评论会显示在这里

接下来写包装函数:

对这一段的评论会显示在这里
import datetime
from django.shortcuts import get_object_or_404
from django.views.generic import list_detail
from mysite.books.models import Author

def author_detail(request, author_id):
    # Delegate to the generic view and get an HttpResponse.
    response = list_detail.object_detail(
        request,
        queryset = Author.objects.all(),
        object_id = author_id,
    )

    # Record the last accessed date. We do this *after* the call
    # to object_detail(), not before it, so that this won't be called
    # unless the Author actually exists. (If the author doesn't exist,
    # object_detail() will raise Http404, and we won't reach this point.)
    now = datetime.datetime.now()
    Author.objects.filter(id=author_id).update(last_accessed=now)

    return response
vayn 03-06 18:33

object_detail() 会返回一个名为 object 的 context

asdsdf 04-07 09:12

sfsdf

roger 11-28 08:11

这里不太合实际,用户访问的话url里不会访问author的id吧。。author的那么更好一点

rainie 02-19 08:53

response = list_detail.object_detail( 这个方法里参数怎么这么少? template_name 和 template_object_name 都不用写么,那怎么对应到html模板呢? 最后一个参数 object_id 又是怎么使用的? 理解不能啊

guosky99 06-09 02:20

object_detail视图函数既然是返回一个对象的详细内容,不明白为什么要有queryset = Author.objects.all()这个参数

Winter 02-20 08:06

1.3版本,已修改为detail.DetailView.as_view

puus lee 10-06 07:27

nice

对这一段的评论会显示在这里

注意

对这一段的评论会显示在这里

除非你添加 last_accessed 字段到你的 Author 模型并创建 books/author_detail.html 模板,否则这段代码不能真正工作。

vayn 03-06 18:35

如果你想偷懒,这里有个现成的模版,base.html 来自第四章 {% extends "base.html" %} {% block title %}Author Last Accessed{% endblock %} {% block content %} <h2>{{ object }}</h2> <ul> <li>{{ object.last_accessed|date:"F j, Y" }}</li> </ul> {% endblock %}

cnbbrcom 05-08 03:26

随便说一下,应该是顺便说一下

Wing shine 11-29 10:43

author_detail.html这个名字 是自动创建的,就如同author_list.html

对这一段的评论会显示在这里

我们可以用同样的方法修改通用视图的返回值。 如果我们想要提供一个供下载用的 纯文本版本的author列表,我们可以用下面这个视图:

对这一段的评论会显示在这里
def author_list_plaintext(request):
    response = list_detail.object_list(
        request,
        queryset = Author.objects.all(),
        mimetype = 'text/plain',
        template_name = 'books/author_list.txt'
    )
    response["Content-Disposition"] = "attachment; filename=authors.txt"
    return response
对这一段的评论会显示在这里

这个方法之所以工作是因为通用视图返回的 HttpResponse 对象可以象一个字典 一样的设置HTTP的头部。 随便说一下,这个 Content-Disposition 的含义是 告诉浏览器下载并保存这个页面,而不是在浏览器中显示它。

cnbbrcom 05-08 03:26

随便说一下,应该是顺便说一下

对这一段的评论会显示在这里

下一章

pker 04-16 11:11

不容易啊,终于把高级看完毕了,感觉高级部分只懂了40%,唉!

Ein 10-04 13:37

没看懂额~,那个list_detail是什么东西。 哎,以后更加熟悉一些了再回来看一遍,现在只入了个门。

roger 11-28 08:19

回楼上,建议看一下django包里的源码

xiaoxu 02-01 13:44

/opt/python2.7/lib/python2.7/site-packages/django ---------- 看下源码,感觉学这个就好多了,不过更耗时间了 /opt/python2.7这个是我的python安装目录

这就能写复杂的网站了? 07-28 03:53

mr.liu 09-15 03:07

这一章严重过时!

对这一段的评论会显示在这里

在这一章我们只讲了Django带的通用视图其中一部分,不过这些方法也适用于其他的 通用视图。 附录C详细地介绍了所有可用的视图,如果你想了解这些强大的特性,推荐你阅读一下。

对这一段的评论会显示在这里

这本书的高级语法部分到此结束。 在下一章, 我们讲解了Django应用的部署。

对这一段的评论会显示在这里