创建一个通用视图
抽取出我们代码中共性的东西是一个很好的编程习惯。比如,像以下的两个Python函数:
def say_hello(person_name):
print 'Hello, %s' % person_name
def say_goodbye(person_name):
print 'Goodbye, %s' % person_name
我们可以把问候语提取出来变成一个参数:
def greet(person_name, greeting):
print '%s, %s' % (greeting, person_name)
通过使用额外的URLconf参数,你可以把同样的思想应用到Django的视图中。
了解这个以后,你可以开始创作高抽象的视图。更具体地说,比如这个视图显示一系列的Event
对象,那个视图显示一系列的BlogEntry
对象,并意识到它们都是一个用来显示一系列对象的视图的特例,而对象的类型其实就是一个变量。
以这段代码作为例子:
# urls.py
from django.conf.urls.defaults import *
from mysite import views
urlpatterns = patterns('',
(r'^events/$', views.event_list),
(r'^blog/entries/$', views.entry_list),
)
# views.py
from django.shortcuts import render_to_response
from mysite.models import Event, BlogEntry
def event_list(request):
obj_list = Event.objects.all()
return render_to_response('mysite/event_list.html', {'event_list': obj_list})
def entry_list(request):
obj_list = BlogEntry.objects.all()
return render_to_response('mysite/blogentry_list.html', {'entry_list': obj_list})
这两个视图做的事情实质上是一样的:显示一系列的对象。让我们把它们显示的对象的类型抽象出来:
# urls.py
from django.conf.urls.defaults import *
from mysite import models, views
urlpatterns = patterns('',
(r'^events/$', views.object_list, {'model': models.Event}),
(r'^blog/entries/$', views.object_list, {'model': models.BlogEntry}),
)
# views.py
from django.shortcuts import render_to_response
def object_list(request, model):
obj_list = model.objects.all()
template_name = 'mysite/%s_list.html' % model.__name__.lower()
return render_to_response(template_name, {'object_list': obj_list})
就这样小小的改动,我们突然发现我们有了一个可复用的,模型无关的视图! 从现在开始,当我们需要一个视图来显示一系列的对象时,我们可以简简单单的重用这一个object_list
视图,而无须另外写视图代码了。 以下是我们做过的事情:
我们通过 model 参数直接传递了模型类。额外URLconf参数的字典是可以传递任何类型的对象,而不仅仅只是字符串。
这一行:
model.objects.all()
是鸭子界定(原文:如果它走路像只鸭子,说话像只鸭子,我们完全可以当它就是只鸭子)因为代码并不需要知道model的具体类型,它只需要知道model有一个objects属性,而且objects有个all()方法。我们使用
model.__name__.lower()
来决定模板的名字。每个Python的类都有一个__name__
属性返回类名。这特性在当我们直到运行时刻才知道对象类型的这种情况下很有用。比如,BlogEntry
类的__name__
就是字符串'BlogEntry'
。这个例子与前面的例子稍有不同,我们传递了一个通用的变量名给模板。 当然我们可以轻易的把这个变量名改成
blogentry_list
或者event_list
,不过我们打算把这当作练习留给读者。
因为数据库驱动的网站都有一些通用的模式,Django提供了一个通用视图的集合,使用它可以节省你的时间。我们将会在下一章讲讲Django的内置通用视图。
{$ activeFileHint $}