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

Django 模版高级进阶

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

回一个django.template.NodeList实例,它是一个包含了所有_Node_对象的列表,这些对象是解析器在解析到任一元组中指定的标签之前遇到的内容.因此在前面的例子中, nodelist 是在 {% comment %} 和 {% endcomment %} 之间所有节点的列表,不包括{% comment %} 和 {% endcomment %} 自身。在 parser.parse() 被调用之后,分析器还没有清除 {% endcomment %} 标签,因此代码需要显式地调用parser.delete_first_token() 来防止该标签被处理两次。之后 CommentNode.render() 只是简单地返回一个空字符串。 在 {% comment %} 和 {% endcomment %} 之间的所有内容都被忽略。分析直至另外一个模板标签并保存内容在前一个例子中, do_comment() 抛弃了{% comment %} 和 {% endcomment %} 之间的所有内容。当然也可以修改和利用下标签之间的这些内容。例如,这个自定义模板标签{% upper %},它会把它自己和{% endupper %}之间的内容变成大写:{% upper %} This will appear in uppercase, {{ user_name }}.{% endupper %}就像前面的例子一样,我们将使用 parser.parse() 。这次,我们将产生的 nodelist 传递给 Node :def do_upper(parser, token): nodelist = parser.parse(('endupper',)) parser.delete_first_token() return UpperNode(nodelist)class UpperNode(template.Node): def __init__(self, nodelist): self.nodelist = nodelist def render(self, context): output = self.nodelist.render(context) return output.upper()这里唯一的一个新概念是 UpperNode.render() 中的 self.nodelist.render(context) 。它对节点列表中的每个Node 简单的调用 render() 。更多的复杂渲染示例请查看 django/template/defaulttags.py 中的 {% if %} 、 {% for %} 、 {% ifequal %}和 {% ifchanged %} 的代码。简单标签的快捷方式许多模板标签接收单一的字符串参数或者一个模板变量引用,然后独立地根据输入变量和一些其它外部信息进行处理并返回一个字符串。 例如,我们先前写的current_time标签就是这样一个例子。 我们给定了一个格式化字符串,然后它返回一个字符串形式的时间。为了简化这类标签,Django提供了一个帮助函数simple_tag。这个函数是django.template.Library的一个方法,它接受一个只有一个参数的函数作参数,把它包装在render函数和之前提及过的其他的必要单位中,然后通过模板系统注册标签。我们之前的的 current_time 函数于是可以写成这样:def current_time(format_string): try: return datetime.datetime.now().strftime(str(format_string)) except UnicodeEncodeError: return ''register.simple_tag(current_time)在Python 2.4中,也可以使用装饰器语法:@register.simple_tagdef current_time(token): # ...有关 simple_tag 辅助函数,需要注意下面一些事情:传递给我们的函数的只有(单个)参数。在我们的函数被调用的时候,检查必需参数个数的工作已经完成了,所以我们不需要再做这个工作。参数两边的引号(如果有的话)已经被截掉了,所以我们会接收到一个普通Unicode字符串。包含标签另外一类常用的模板标签是通过渲染 其他 模板显示数据的。 比如说,Django的后台管理界面,它使用了自定义的模板标签来显示新增/编辑表单页面下部的按钮。 那些按钮看起来总是一样的,但是链接却随着所编辑的对象的不同而改变。 这就是一个使用小模板很好的例子,这些小模板就是当前对象的详细信息。这些排序标签被称为 包含标签 。如何写包含标签最好通过举例来说明。 让我们来写一个能够产生指定作者对象的书籍清单的标签。 我们将这样利用标签:{% books_for_author author %}结果将会像下面这样:<ul> <li>The Cat In The Hat</li> <li>Hop On Pop</li> <li>Green Eggs And Ham</li></ul>首先,我们定义一个函数,通过给定的参数生成一个字典形式的结果。 需要注意的是,我们只需要返回字典类型的结果就行了,不需要返回更复杂的东西。 这将被用来作为模板片段的内容:def books_for_author(author): books = Book.objects.filter(authors__id=author.id) return {'books': books}接下来,我们创建用于渲染标签输出的模板。 在我们的例子中,模板很简单:<ul>{% for book in books %} <li>{{ book.title }}</li>{% endfor %}</ul>最后,我们通过对一个 Library 对象使用 inclusion_tag() 方法来创建并注册这个包含标签。在我们的例子中,如果先前的模板在 polls/result_snippet.html 文件中,那么我们这样注册标签:register.inclusion_tag('book_snippet.html')(books_for_author)Python 2.4装饰器语法也能正常工作,所以我们可以这样写:@register.inclusion_tag('book_snippet.html')def books_for_author(author): # ...有时候,你的包含标签需要访问父模板的context。 为了解决这个问题,Django为包含标签提供了一个takes_context 选项。 如果你在创建模板标签时,指明了这个选项,这个标签就不需要参数,并且下面的Python函数会带一个参数: 就是当这个标签被调用时的模板context。例如,你正在写一个包含标签,该标签包含有指向主页的 home_link 和 home_title 变量。 Python函数会像这样:@register.inclusion_tag('link.html', takes_context=True)def jump_link(context): return { 'link': context['home_link'], 'title': context['home_title'], }(注意函数的第一个参数 必须 是 context 。)模板 link.html 可能包含下面的东西:Jump directly to <a href="{{ link }}">{{ title }}</a>.然后您想使用自定义标签时,就可以加载它的库,然后不带参数地调用它,就像这样:{% jump_link %}编写自定义模板加载器Djangos 内置的模板加载器(在先前的模板加载内幕章节有叙述)通常会满足你的所有的模板加载需求,但是如果你有特殊的加载需求的话,编写自己的模板加载器也会相当简单。 比如:你可以从数据库中,或者利用Python的绑定直接从Subversion库中,更或者从一个ZIP文档中加载模板。模板加载器,也就是 TEMPLATE_LOADERS 中的每一项,都要能被下面这个接口调用:load_template_source(template_name, template_dirs=None)参数 template_name 是所加载模板的名称 (和传递给 loader.get_template() 或者 loader.select

上一页  [1] [2] [3] [4] [5] [6] [7]  下一页


Django 模版高级进阶