资讯专栏INFORMATION COLUMN

web.py源码分析: 模板(2)

figofuture / 2973人阅读

摘要:上一篇文章源码分析模板说明了的模板的大致工作原理。本文重点讲述模板支持的语法是如何转换生成函数的。模板的名称统一是。模板代码断行模板内容函数内容从结果来看,模板中的断行只是为了不再结果中插入一个多余的换行符而已。

上一篇文章web.py源码分析: 模板(1)说明了web.py的模板的大致工作原理。本文重点讲述web.py模板支持的语法是如何转换生成__template__函数的。

web.py模板语法和__template__()函数的对应关系

本章会列出模板内容以及转换之后的__template__()函数的内容,以及必要的文字说明。模板的名称统一是hello.html

纯字符串

模板内容

hello, world

函数内容

def __template__():
    __lineoffset__ = -5
    loop = ForLoop()
    self = TemplateResult(); extend_ = self.extend
    extend_([u"hello, world
"])

    return self
def with

模板内容

$def with (name, value=[], *args, **kargs)
hello, $name

函数内容

def __template__ (name, value=[], *args, **kargs):
    __lineoffset__ = -4
    loop = ForLoop()
    self = TemplateResult(); extend_ = self.extend
    extend_([u"hello, ", escape_(name, True), u"
"])

    return self
    

从生成的函数可以看出,def with语法所生成的就是__template__()函数的参数列表。

表达式替换

模板内容

$def with (name, value)
$name
${name + value}
$(name + value)ing.
$name[value].function()

函数内容

def __template__ (name, value):
    __lineoffset__ = -4
    loop = ForLoop()
    self = TemplateResult(); extend_ = self.extend
    extend_([escape_(name, True), u"
"])
    extend_([escape_((name + value), True), u"
"])
    extend_([escape_((name + value), True), u"ing.
"])
    extend_([escape_(name[value].function(), True), u"
"])

    return self

表达式的替换就是执行表达式(表达式对应的代码),得到的结果添加到TemplateResult实例中。

赋值

模板内容

$def with (name, func)
$ name1 = name
$ name2 = func()

函数内容

def __template__ (name, func):
    __lineoffset__ = -4
    loop = ForLoop()
    self = TemplateResult(); extend_ = self.extend
    name1 = name
    name2 = func()

    return self

其实,转换后就是Python代码里的赋值语句。

内容过滤

模板内容

$def with (name)
$name
$:name

函数内容

def __template__ (name):
    __lineoffset__ = -4
    loop = ForLoop()
    self = TemplateResult(); extend_ = self.extend
    extend_([escape_(name, True), u"
"])
    extend_([escape_(name, False), u"
"])

    return self

从生成的代码来看,是否使用过滤语法的区别就是传入excape_函数的第二个参数,这个函数其实只是一个字符串处理函数,后续再说。

模板代码断行(newline suppression)

模板内容

$def with (name, func)
$name
hello, 
$name 
!
$func(1, 2, 3, 4, 5)

函数内容

def __template__ (name, func):
    __lineoffset__ = -4
    loop = ForLoop()
    self = TemplateResult(); extend_ = self.extend
    extend_([escape_(name, True), u"
"])
    extend_([u"hello, "])
    extend_([escape_(name, True), u" "])
    extend_([u"!
"])
    extend_([escape_(func(1, 2, 3, 4, 5), True), u"
"])

    return self

从结果来看,模板中的断行只是为了不再结果中插入一个多余的换行符而已。另外,一个表达式的中间是不支持断行的,就比如在模板中不能把func函数的参数列表写成两行。

$符号

模板内容

$$

函数内容

def __template__():
    __lineoffset__ = -5
    loop = ForLoop()
    self = TemplateResult(); extend_ = self.extend
    extend_([u"$", u"
"])

    return self
    
注释

模板内容

$# comment line
hello, world.

函数内容

def __template__():
    __lineoffset__ = -5
    loop = ForLoop()
    self = TemplateResult(); extend_ = self.extend
    extend_([u"
"])
    extend_([u"hello, world.
"])

    return self

模板中注释的行在生成的函数中只有一个换行符。

控制结构 for循环

模板内容

$for i in range(10):
    I like $i

函数内容

def __template__():
    __lineoffset__ = -5
    loop = ForLoop()
    self = TemplateResult(); extend_ = self.extend
    for i in loop.setup(range(10)):
        extend_([u"I like ", escape_(i, True), u"
"])

return self

模板中的for循环被转换成了代码中的for循环,而且用上了变量loop(ForLoop对象后续再来看)。

while循环

模板内容

$def with (name_list)

$while name_list:
    hello, $name_list.pop()

函数内容

def __template__ (name_list):
    __lineoffset__ = -4
    loop = ForLoop()
    self = TemplateResult(); extend_ = self.extend
    extend_([u"
"])
    while name_list:
        extend_([u"hello, ", escape_(name_list.pop(), True), u"
"])

    return self
    

注意和for循环的区别,没有使用loop变量。

for循环的loop变量

模板内容

$def with (name_list)
$for name in name_list:
    $loop.index
    $loop.index0
    $loop.first
    $loop.last
    $loop.odd
    $loop.even
    $loop.parity
    $loop.parent
    hello, $name

$for i in range(10):
    $for name in name_list:
        $loop.parent
        hello, $name

函数内容

def __template__ (name_list):
    __lineoffset__ = -4
    loop = ForLoop()
    self = TemplateResult(); extend_ = self.extend
    for name in loop.setup(name_list):
        extend_([escape_(loop.index, True), u"
"])
        extend_([escape_(loop.index0, True), u"
"])
        extend_([escape_(loop.first, True), u"
"])
        extend_([escape_(loop.last, True), u"
"])
        extend_([escape_(loop.odd, True), u"
"])
        extend_([escape_(loop.even, True), u"
"])
        extend_([escape_(loop.parity, True), u"
"])
        extend_([escape_(loop.parent, True), u"
"])
        extend_([u"hello, ", escape_(name, True), u"
"])
        extend_([u"
"])
    for i in loop.setup(range(10)):
        for name in loop.setup(name_list):
            extend_([escape_(loop.parent, True), u"
"])
            extend_([u"hello, ", escape_(name, True), u"
"])

    return self

这里展示了loop变量的成员,以及嵌套循环的使用。

if-else

模板内容

$def with (name_list)
$if name_list:
    $len(name_list)
$else:
    0

函数内容

def __template__ (name_list):
    __lineoffset__ = -4
    loop = ForLoop()
    self = TemplateResult(); extend_ = self.extend
    if name_list:
        extend_([escape_(len(name_list), True), u"
"])
    else:
        extend_([u"0
"])

    return self

elif语句也支持。

函数定义

模板内容

$def with (name_list)

$def hello(name):
    hello, $name

$def hello_to_all(nlist):
    $for each in nlist:
        $hello(each)

$hello_to_all(name_list)

函数内容

def __template__ (name_list):
    __lineoffset__ = -4
    loop = ForLoop()
    self = TemplateResult(); extend_ = self.extend
    extend_([u"
"])
    __lineoffset__ -= 3
    def hello(name):
        self = TemplateResult(); extend_ = self.extend
        extend_([u"hello, ", escape_(name, True), u"
"])
        extend_([u"
"])
        return self
    __lineoffset__ -= 3
    def hello_to_all(nlist):
        self = TemplateResult(); extend_ = self.extend
        for each in loop.setup(nlist):
            extend_([escape_(hello(each), True), u"
"])
            extend_([u"
"])
        return self
    extend_([escape_(hello_to_all(name_list), True), u"
"])

    return self

模板对函数的支持其实就是定义内部函数并且调用,每个内部函数的返回结果也都是TemplateResult实例。

code

模板内容

$def with (name_list)

$code:
  new_list = [x.upper() for x in name_list]
  def hello(name):
      return "hello, %s" % (name)

  more_new_list = []
  for each in new_list:
      more_new_list.append(hello(each))

$hello("everybody")
$len(more_new_list)

函数内容

def __template__ (name_list):
    __lineoffset__ = -4
    loop = ForLoop()
    self = TemplateResult(); extend_ = self.extend
    extend_([u"
"])

    new_list = [x.upper() for x in name_list]
    def hello(name):
        return "hello, %s" % (name)

    more_new_list = []
    for each in new_list:
        more_new_list.append(hello(each))

    extend_([escape_(hello("everybody"), True), u"
"])
    extend_([escape_(len(more_new_list), True), u"
"])

    return self

code的语法有点复杂,其内部是用来定义原始的Python代码的,有如下几个特点:

code内部定义的函数也是内部函数,在模板的其他地方可以调用,但是不会把结果存放在TemplateResult实例中返回。

code中定义的变量都会作为__template__()函数的局部变量,在模板的其他地方可以调用。

注意,code块中不要使用print语句打印输出(虽然默认已经禁止了)。

var

模板内容

$def with (name_list)
$var title: hi
$var title2: "hi"
$var name: $name_list[0]
$var name2: name_list[0]

函数内容

def __template__ (name_list):
    __lineoffset__ = -4
    loop = ForLoop()
    self = TemplateResult(); extend_ = self.extend
    self["title"] = join_(u"hi")
    self["title2"] = join_(u""hi"")
    self["name"] = join_(escape_(name_list[0], True))
    self["name2"] = join_(u"name_list[0]")

    return self

var是用来为模板设置属性的,从生成的代码来看,就是为TemplateResult实例设置属性。上面的模板内容里有一些关键细节:

var name: value中的冒号后面的内容默认是作为字符串处理的,可以不用加引号,如果加了引号,则引号也会作为内容的一部分。

如果要在冒号后面访问一些变量值,需要使用$前缀。

总结

写了这些web.py模板支持的语法和生成的代码的对应关系,希望有助于大家理解模板的语法,了解每种语法的用途,避免踩坑。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/45358.html

相关文章

  • web.py源码分析: 模板(1)

    摘要:模板函数到底长什么样下面我们就可以来看看模板函数到底长什么样了。当然,首先得创建一个模板文件。总结通过打印中间结果和分析代码,我们已经大概知道了的模板是如何转化成内容的。下一篇文章会阐述模板的各种语法所对应的动态函数内容。 web.py模板的实现原理 web.py的模板实现利用了Python的可执行对象的动态特性:根据模板内容和渲染函数的参数创建一个函数,该函数执行的时候会返回一个Te...

    Rocko 评论0 收藏0
  • web.py源码分析: 模板(3)

    摘要:前两篇文章主要说明了的模板系统将模板文件处理后得到的结果函数。生成函数的代码这个是模板生成过程中最长最复杂的一段,会应用到的分析功能以及动态编译功能。参数都是一个,表示还未解析的模板内容。 前两篇文章主要说明了web.py的模板系统将模板文件处理后得到的结果:__template__()函数。本文主要讲述模板文件是如何变成__template__()函数的。 Render和frende...

    OnlyMyRailgun 评论0 收藏0
  • web.py源码分析: application(1)

    摘要:本文主要分析的是库的这个模块中的代码。将结果转换成一个迭代器。函数函数的定义如下位置位置位置该函数的参数中就是,是路由映射表则是,是本次请求路径。位置,如果是其他情况,比如直接指定一个类对象作为处理对象。 本文主要分析的是web.py库的application.py这个模块中的代码。总的来说,这个模块主要实现了WSGI兼容的接口,以便应用程序能够被WSGI应用服务器调用。WSGI是We...

    edgardeng 评论0 收藏0
  • 基于Linux环境的Web.py框架介绍

    摘要:前言在文章基于环境搭建框架方法介绍中介绍了客户端和服务器的交互过程,服务器接收客户端的请求后,由应用服务器对浏览器的请求进行处理,将生成的响应传递给服务器,再由服务器返回给客户端。 前言 在文章《基于Linux环境搭建Nginx+uWSGI+Python框架方法介绍》中介绍了客户端和Web服务器的交互过程,Web服务器接收客户端的请求后,由Web应用服务器对浏览器的请求进行处理,将生成...

    caikeal 评论0 收藏0
  • newrelic python agent 源码分析-1

    摘要:是应用性能管理监控解决方案提供商。目录是列出的命令脚本所在目录。包含文件如下的函数是命令执行的入口。而对于硬件信息的检测则由进行。文档地址源码仔细看下去,太复杂了。下一篇再分析一个请求到结束探针工作的完整过程吧。 Newrelic 是APM(Application Performance Management)(应用性能管理/监控)解决方案提供商。项目中,通常用它来追踪应用的性能。最近...

    szysky 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<