当前位置:K88软件开发文章中心网站服务器框架django → 文章内容

Django 通用视图

减小字体 增大字体 作者:佚名  来源:网上搜集  发布时间:2019-1-25 14:19:21

er_list.html" ,其中books部分是定义这个模型的app的名称, publisher部分是这个模型名称的小写。这个模板将按照 context 中包含的变量 object_list 来渲染,这个变量包含所有的书籍对象。 一个非常简单的模板看起来象下面这样:{% 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,这样变量所代表的内容就显而易见了。我们可以很容易地像下面这样修改 template_object_name 参数的名称:from django.conf.urls.defaults import *from django.views.generic import list_detailfrom mysite.books.models import Publisherpublisher_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的方式来创建一个表示列表项目的变量名。使用有用的 template_object_name 总是个好想法。 你的设计模板的合作伙伴会感谢你的。添加额外的Context你常常需要呈现比通用视图提供的更多的额外信息。 例如,考虑一下在每个出版商的详细页面显示所有其他出版商列表。 object_detail 通用视图为context提供了出版商信息,但是看起来没有办法在模板中 获取 所有 出版商列表。这是解决方法: 所有的通用视图都有一个额外的可选参数 extra_context 。这个参数是一个字典数据类型,包含要添加到模板的context中的额外的对象。 所以要给视图提供所有出版商的列表,我们就用这样的info字典:publisher_info = { 'queryset': Publisher.objects.all(), 'template_object_name': 'publisher', 'extra_context': {'book_list': Book.objects.all()}}这样就把一个 {{ book_list }} 变量放到模板的context中。 这个方法可以用来传递任意数据 到通用视图模板中去,非常方便。 这是非常方便的不过,这里有一个很隐蔽的BUG,不知道你发现了没有?我们现在来看一下, extra_context 里包含数据库查询的问题。 因为在这个例子中,我们把Publisher.objects.all() 放在URLconf中,它只会执行一次(当URLconf第一次加载的时候)。 当你添加或删除出版商,你会发现在重启Web服务器之前,通用视图不会反映出这些修改(有关QuerySet何时被缓存和赋值的更多信息请参考附录C中“缓存与查询集”一节)。备注这个问题不适用于通用视图的 queryset 参数。 因为Django知道有些特别的 QuerySet 永远不能 被缓存,通用视图在渲染前都做了缓存清除工作。解决这个问题的办法是在 _extracontext 中用一个回调(callback)来代替使用一个变量。 任何传递给extra_context的可调用对象(例如一个函数)都会在每次视图渲染前执行(而不是只执行一次)。 你可以象这样定义一个函数: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 本身就是可以调用的: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),)这是一个相当简单的例子,但是很说明问题。 当然,你通常还想做比重新排序更多的事。 如果你想要呈现某个特定出版商出版的所有书籍列表,你可以使用同样的技术: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),)注意 在使用一个过滤的 queryset 的同时,我们还使用了一个自定义的模板名称。 如果我们不这么做,通用视图就会用以前的模板,这可能不是我们想要的结果。同样要注意的是这并不是一个处理出版商相关书籍的最好方法。 如果我们想要添加另一个 出版商页面,我们就得在URL配置中写URL配置,如果有很多的出版商,这个方法就不能 接受了。 在接下来的章节我们将来解决这个问题。用函数包装来处理复杂的

上一页  [1] [2] [3]  下一页


Django 通用视图