编写自定义的Django模板加载器的简单示例
Djangos内置的模板加载器(在先前的模板加载内幕章节有叙述)通常会满足你的所有的模板加载需求,但是如果你有特殊的加载需求的话,编写自己的模板加载器也会相当简单。比如:你可以从数据库中,或者利用Python的绑定直接从Subversion库中,更或者从一个ZIP文档中加载模板。
模板加载器,也就是TEMPLATE_LOADERS中的每一项,都要能被下面这个接口调用:
load_template_source(template_name,template_dirs=None)
参数template_name是所加载模板的名称(和传递给loader.get_template()或者loader.select_template()一样),而template_dirs是一个可选的代替TEMPLATE_DIRS的搜索目录列表。
如果加载器能够成功加载一个模板,它应当返回一个元组:(template_source,template_path)。在这里的template_source就是将被模板引擎编译的的模板字符串,而template_path是被加载的模板的路径。由于那个路径可能会出于调试目的显示给用户,因此它应当很快的指明模板从哪里加载。
如果加载器加载模板失败,那么就会触发django.template.TemplateDoesNotExist异常。
每个加载函数都应该有一个名为is_usable的函数属性。这个属性是一个布尔值,用于告知模板引擎这个加载器是否在当前安装的Python中可用。例如,如果pkg_resources模块没有安装的话,eggs加载器(它能够从pythoneggs中加载模板)就应该把is_usable设为False,因为必须通过pkg_resources才能从eggs中读取数据。
一个例子可以清晰地阐明一切。这儿是一个模板加载函数,它可以从ZIP文件中加载模板。它使用了自定义的设置TEMPLATE_ZIP_FILES来取代了TEMPLATE_DIRS用作查找路径,并且它假设在此路径上的每一个文件都是包含模板的ZIP文件:
fromdjango.confimportsettings fromdjango.templateimportTemplateDoesNotExist importzipfile defload_template_source(template_name,template_dirs=None): "TemplateloaderthatloadstemplatesfromaZIPfile." template_zipfiles=getattr(settings,"TEMPLATE_ZIP_FILES",[]) #TryeachZIPfileinTEMPLATE_ZIP_FILES. forfnameintemplate_zipfiles: try: z=zipfile.ZipFile(fname) source=z.read(template_name) except(IOError,KeyError): continue z.close() #Wefoundatemplate,soreturnthesource. template_path="%s:%s"%(fname,template_name) return(source,template_path) #Ifwereachhere,thetemplatecouldn'tbeloaded raiseTemplateDoesNotExist(template_name) #Thisloaderisalwaysusable(sincezipfileisincludedwithPython) load_template_source.is_usable=True
我们要想使用它,还差最后一步,就是把它加入到TEMPLATE_LOADERS。如果我们将这个代码放入一个叫mysite.zip_loader的包中,那么我们要把mysite.zip_loader.load_template_source加到TEMPLATE_LOADERS中。