设为首页 收藏本站
查看: 1213|回复: 0

[经验分享] web.py templating system (codename: templetor)

[复制链接]

尚未签到

发表于 2015-11-5 10:15:56 | 显示全部楼层 |阅读模式
  
  There are almost as many Python templating systems as there are web frameworks (and, indeed, it seems like many templating systems are adopting web framework-like features), so it is with some trepidation that I work on a new one. Sadly, again I find that my requirements are met by nothing else:


  • The templating system has to look decent. No <%#foo#%> crud.
  • Reuse Python terms and semantics as much as possible.
  • Expressive enough to do real computation.
  • Usable for any text language, not just HTML and XML.
  And requirements for the implementation as well:


  • Sandboxable so that you can let untrusted users write templates.
  • Simple and fast implementation.
  So here's my entry.

Variable substitution

Look, a $string.
Hark, an ${arbitrary + expression}.
Gawk, a $dictionary[key].function('argument').
Cool, a $(limit)ing.
Stop, /$money isn't evaluated.

  We use basically the same semantics as (rejected) PEP 215. Variables can go anywhere in a document.

Newline suppression

If you put a backslash /
at the end of a line /
(like these) /
then there will be no newline.

  renders as all one line.

Expressions

Here are some expressions:
$for var in iterator: I like $var!
$if times > max:
Stop! In the name of love.
$else:
Keep on, you can do it.
That's all, folks.

  All your old Python friends are here: if, while, for, else, break, continue, and pass also act as you'd expect. (Obviously, you can't have variables named any of these.) The Python code starts at the $ and ends at the :. The $ has to be at the beginning of the line, but that's not such a burden because of newline suppression (above).
  Also, we're very careful about spacing -- all the lines will render with no spaces at the beginning. (Open question: what if you want spaces at the beginning?) Also, a trailing space might break your code.
  There are a couple changes from Python: for and while now take an else clause that gets called if the loop is never evaluated.
  (Possible feature to add: Django-style for loop variables.)

Comments

$# Here's where we hoodwink the folks at home:
Please enter in your deets:
CC: [       ]  $#this is the important one
SSN: $#Social Security Number#$ [       ]

  Comments start with $# and go to #$ or the end of the line, whichever is first.

Code
  NOTE: This feature has not been implemented in the current web.py implementation of templetor.

Sometimes you just need to break out the Python.
$ mapping = {
$   'cool': ['nice', 'sweet', 'hot'],
$   'suck': ['bad', 'evil', 'awful']
$ }
Isn't that $mapping[thought]?
That's$ del mapping $ fine with me.
$ complicatedfunc()
$ for x in bugs:
$ if bug.level == 'severe':
Ooh, this one is bad.
$ continue
And there's $x...

  Body of loops have to be indented with exactly 4 spaces.
  Code begins with a $ and a space and goes until the next $ or the end of the line, whichever comes first. Nothing ever gets output if the first character after the $ is a space (so complicatedfunc above doesn't write anything to the screen like it might without the space).

Python integration
  A template begins with a line like this:

$def with (name, title, company='BigCo')

  which declares that the template takes those arguments. (The with keyword is special, like def or if.)
  Don't forget to put spaces in the definition
  The following will not work:

$def with (name,title,company='BigCo')

  Inside Python, the template looks like a function that takes these arguments. It returns a storage object with the special property that evaluating it as a string returns the value of the body of the template. The elements in the storage object are the results of the defs and the sets.
  Perhaps an example will make this clearer. Here's a template, "entry":

$def with (post)
$var title: $post.title
<p>$markdown(post.body)</p>
<p class="byline">by $post.author</p>

  Here's another; "base":

$def with (self)
<html><head>
<title>$self.title</title>
</head><body>
<h1>$self.title</h1>
$:self
</body></html>

  Now let's say we compile both from within Python, the first as entry, the second as base. Here's how we might use them:

print base( entry( post ) )

  entry takes the argument post and returns an object whose string value is a bit of HTML showing the post with its title in the property title. base takes this object and places the title in the appropriate place and displays the page itself in the body of the page. The Python code prints out the result.
  _Where did markdown come from? It wasn't passed as an argument._ You can pass a list of functions and variables to the template compiler to be made globally available to templates. Why $:self? See below
  Here's an example:

import template
render = template.render('templates/')
template.Template.globals['len'] = len
print render.base(render.message('Hello, world!'))

  The first line imports templetor. The second says that our templates are in the directory templates/. The third give all our templates access to the len function. The fourth grabs the template message.html, passes it the argument 'Hello, world!', passes the result of rendering it to mcitp the template base.html and prints the result. (If your templates don't end in .html or .xml, templetor will still find them, but it won't do its automatic HTML-encoding.)

Turning Off Filter
  By default template.render will use web.websafe filter to do HTML-encoding. To turn it off, put a : after the $ as in:

$:form.render()

  Output from form.render() will be displayed as is.

$:fooBar    $# fooBar = <span>lorem ipsum</span>

  Output from variable in template will be displayed as is.

Including / nesting templates
  If you want to nest one template within another, you nest the render() calls, and then include the variable (unfiltered) in the page. In your handler:

print render.foo(render.bar())

  or (to make things a little more clear):

barhtml = render.bar()
print render.foo(barhtml)

  Then in the template foo.html:

$def with (bar)
html goes here
$:bar
more html

  This replaces the $:bar with the output of the render.bar() call (which is why it must be $:/unfiltered, so ccnp that you get un-encoded HTML (unless you want something else of course)). You can pass variables in, in the same way:

print render.foo(render.bar(baz), qux)

  In the template bar (bar.html):

$def with (baz)
bar stuff goes here + baz

  In template foo (foo.html):

$def with (bar, qux)
html goes here
$:bar
Value of qux is $qux

Links
  

Edit History Last Modified August 11
版权声明:本文为博主原创文章,未经博主允许不得转载。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-135353-1-1.html 上篇帖子: CCNP路由实验之十三 Qos 下篇帖子: 给想从事运维工作的非相关专业的大学生的建议
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表