一、模板 一个网站有很多结构相同的网页 ,使用模板能有效的避免繁琐重复的工作:
1)、在templates文件夹(与xxx.html同层)下新建base文件夹来存放模板
#base.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{{ Title }}</title>
{% block head_css %}
{% endblock %}
{% block head_js %}
{% endblock %}
</head>
<body>
{% block header %}
{% endblock %}
{% block container %}
{% endblock %}
{% block footer %}
{% endblock %}
{% block foot_js %}
{% endblock %}
</body>
</html>
#login.html
{% extends 'base/base.html' %} #载入模板
{% block container %} #对应base.html <bady> 中的container位置
<form method="get" enctype="multipart/form-data">
{{ lf.as_p }}
<a href="http://127.0.0.1:8000/register">注册</a> <input type="submit" value="登录">
</form>
{% endblock %}
二、 自定义标签
当遇到一个模板标签(template tag)时,模板解析器就会把标签包含的内容,以及模板解析器自己作为参数调用一个python函数。 这个函数负责返回一个和当前模板标签内容相对应的节点(Node)的实例。
根据官方文档首先我们要在APP目录下创建templatetags包,在这个包内实现自定义标签。
方法一:
#upper.py
from django import template
register = template.Library()
class UpperNode(template.Node):
def __init__(self,nodelist):
self.nodelist = nodelist
def render(self, context):
contand = self.nodelist.render(context)
return contand.upper()
@register.tag
def upper(parser,token):
nodelist = parser.parse('endupper')
parser.delete_first_token()
return UpperNode(nodelist)
'''
@register.tag(name="current_time")
def do_current_time(parser, token):
# ...
@register.tag
def shout(parser, token):
# ...
如果你像在第二个例子中那样忽略 name 参数的话,Django会使用函数名称作为标签名称。
'''
#login.html
{% extends 'base/base.html' %}
{% block container %}
{% load upper %} #载入 upper 开始解析
{% upper %} #运行 upper
Willcome {{ custom_name }}
{% endupper %} #停止解析
...
...
{% endblock %}
这里需要说明的是
每个标签编译函数有两个参数,parser和token。parser是模板解析器对象。 我们在这个例子中是指 解析到 ‘endupper’ 停止 。 token是正在被解析的语句。
nodelist 存放粗出的节点 此处是 ‘Willcome {{ custom_name }}’ , UpperNode函数进行处理,返回大写字符串。
方法二:在templatetags 文件夹下创建 current_time.py
from django import template
import datetime
register = template.Library() #实例化Library()
class CurrentTimeNode(template.Node):
def __init__(self, format_string):
self.format_string = str(format_string)
def render(self, context):
now = datetime.datetime.now()
return now.strftime(self.format_string)
def do_current_time(parser, token):
try:
# split_contents() knows not to split quoted strings.
tag_name, format_string = token.split_contents()
except ValueError:
msg = '%r tag requires a single argument' % token.split_contents()[0]
raise template.TemplateSyntaxError(msg)
return CurrentTimeNode(format_string[1:-1])
register.tag('current_time', do_current_time) #注册标签
这里需要说明的地方很多:
- 每个标签编译函数有两个参数,parser和token。parser是模板解析器对象。 我们在这个例子中并不使用它。
token是正在被解析的语句。 - token.contents 是包含有标签原始内容的字符串。 在我们的例子中,它是 ‘current_time “%Y-%m-%d
%I:%M %p”’ 。 - token.split_contents() 方法按空格拆分参数同时保证引号中的字符串不拆分。 应该避免使用
token.contents.split() (仅使用Python的标准字符串拆分)。
它不够健壮,因为它只是简单的按照所有空格进行拆分,包括那些引号引起来的字符串中的空格。 - 这个函数可以抛出 django.template.TemplateSyntaxError ,这个异常提供所有语法错误的有用信息。
- 不要把标签名称硬编码在你的错误信息中,因为这样会把标签名称和你的函数耦合在一起。
token.split_contents()[0]总是记录标签的名字,就算标签没有任何参数。 - 这个函数返回一个 CurrentTimeNode (稍后我们将创建它),它包含了节点需要知道的关于这个标签的全部信息。
在这个例子中,它只是传递了参数 “%Y-%m-%d %I:%M %p” 。模板标签开头和结尾的引号使用
format_string[1:-1] 除去。 - 模板标签编译函数 必须 返回一个 Node 子类,返回其它值都是错的。
- 这两个函数( init() 和 render() )与模板处理中的两步(编译与渲染)直接对应。 这样,初始化函数仅仅需要存储后面要用到的格式字符串,而 render() 函数才做真正的工作。
- 与模板过滤器一样,这些渲染函数应该静静地捕获错误,而不是抛出错误。 模板标签只允许在编译的时候抛出错误。
最后,你需要用你模块的Library 实例注册这个标签。 注册自定义标签与注册自定义过滤器非常类似(如前文所述)。 只需实例化一个 template.Library 实例然后调用它的 tag() 方法。 例如:
register.tag('current_time', do_current_time) tag() 方法需要两个参数: ×模板标签的名字(字符串)。 ×编译函数。
{% extends 'base/base.html' %}
{% block container %}
{% load current_time %} #载入 current_time
<p>The time is {% current_time "%Y-%m-%d %I:%M %p" %}.</p>
#运行current_time 参数 "%Y-%m-%d %I:%M %p"
...
...
{% endblock %}
参考:官方文档

本文介绍了如何在网站开发中利用模板系统简化页面布局,并通过自定义标签增强模板的灵活性。详细展示了两种自定义标签的方法及其应用案例。
125

被折叠的 条评论
为什么被折叠?



