当前位置: 首页 > 工具软件 > karrigell > 使用案例 >

Karrigell中的脚本样式(Script styles) (二)

罗智刚
2023-12-01

Karrigell中的脚本样式(Script styles) (二)

4 HTML Inside Python

HTML Inside Python(HIP)是PIH的镜像;它是HTML代码在Python脚本内部,打印参数更简单。你可以用两种方式:

1)对于短的HTML代码块,用引用开始一行,不用print语句:HIP将会在执行的时候增加语句,在执行的时候

import os

currentDir=os.getcwd()

"Current directory is <b>"+currentDir+"</b>"

2)对于长一些的块,使用Python多行字符串声明,用三个引号:

the_smiths={'vocals':'Morrissey',

    'guitar':'Johnny Marr',

    'the bass guitar':'Andy Rourke',

    'the drums':'Mike Joyce'}

"""

<table border=1>

<tr backgroundcolor=green>

<td>One of the best pop bands ever</td>

</tr>

</table>

<table>

"""

for item in the_smiths.keys():

    "<tr><td>%s</td><td>%s</td></tr>" %(item,the_smiths[item])

"</table>"

 

5.HTMLTags - generate HTML in Python

5.1 Overview

HTMLTags模块定义了一个类,为了所有的有效的HTML标签,用大写字母写的。为了创建一个HTML片段,普通的声明用:

t = TAG(content, key1=val1,key2=val2,...)

那么print t的结果是:

<TAG key1="val1" key2="val2" ...>content</TAG>

举例

print A('bar', href="foo")   ==> <A href="foo">bar</A>

和Python关键词同名的属性必须要大写

print DIV('bar', Class="title")   ==> <DIV Class="title">bar</A>

产生HTML属性不带值的,给它们赋值为True

print OPTION('foo',SELECTED=True,value=5)   ==> <OPTION value="5" SELECTED>

对于非关闭的标签,像是<IMG>或者<BR>,print语句不会产生关闭的标签

5.2Tags concatenation 标签相关联的

增加一个brother到一个标签(在树的同一层的元素)使用加法操作:

print B('bar')+INPUT(name="bar")   ==> <B>bar</B><INPUT name="bar">

可以使用乘法操作来实现重复:

print TH('&nbsp')*3   ==> <TD>&nbsp;</TD><TD>&nbsp;</TD><TD>&nbsp;</TD>

如果你有一个实例列表,你可以用Sum()函数把这些条目联系起来:

Sum([ (I(i)+':'+B(i*i)+BR()) for i in range(100) ])

产生表格的行,显示0到99的平方

5.3 Building an HTML document

一个HTML文档是一个元素树;HTMLTags提供了一个简单的方法来建立这个树

content参数可以是一个HTMLTags类,因此你可以嵌套tags,像这样:

print B(I('foo'))   ==> <B><I>foo</I></B>

如果你把这个文档想象成一颗树,这就意味着实例I('foo')是实例B类的一个孩子

如果你需要建立一个更加复杂的树,使用这个方法意味着你将要当心打开和关闭括号,代码将会很快的变得难以阅读和维护。这也意味着你是自底向上建立的树

一个相关的方法是自顶向下的建立树:首先建立嵌套的元素,然后添加它们的孩子。HTMLTags使用<=操作符作为添加孩子的同义词

你可以比较这两种方法:

自底向上:

# build lines first 

lines = INPUT(name="zone1",value=kw.get("zone1","")) 

lines += BR()+INPUT(name="zone2",value=kw.get("zone2","")) 

lines += BR()+INPUT(Type="submit",value="Ok") 

# build and print form 

print FORM(lines,action="validate",method="post")

自顶向下

# build form first 

form = FORM(action="validate",method="post") 

# add child elements 

form <= INPUT(name="zone1",value=kw.get("zone1","")) 

form <= BR()+INPUT(name="zone2",value=kw.get("zone2",""))

form <= BR()+INPUT(Type="submit",value="Ok") 

print form

在建立一个复杂的文档的时候自顶向下的方法可能会更加易读

head = HEAD()

head <= LINK(rel="Stylesheet",href="doc.css")

head <= TITLE('Record collection')+stylesheet

 

body = BODY()

body <= H1('My record collection')

 

table = TABLE(Class="content")

table <= TR(TH('Title')+TH('Artist'))

for rec in records:

    table <= TR(TD(rec.title,Class="title")+TD(rec.artist,Class="Artist")

 

body <= table

print HTML(head+body)

 5.4 Inspecting the document tree 检查文档树

 Tags有两种方法来寻找匹配的元素

 1)get_by_tag(tag_name):返回元素列表,有指定的标签名的

 2)get_by_attr(arg1=val1,arg2=val2...):返回元素列表,匹配这个情况的属性

 举例,如果你建立了一个表格并且想要用不同的样式来表现奇偶行,你可以使用get_by_tag()并且改变TD的Class属性:

 classes = ['row_even','row_odd']

lines = table.get_by_tag('TR')

for i,line in enumerate(lines):

    cells = line.get_by_tag('TD')

    for cell in cells:

        cell.attrs['Class'] = classes[i%2]

5.5选择标签,checkboxes和radiobuttons

当建立一个HTML文档时,经常会有一系列的数据(请求数据库的结果)将会打印给终端用户,作为一个列表选项,在SELECT标签中,或者作为一些raiobuttons或者checkboxes。通常一个或者多个选项被选择,因为匹配了条件

HTMLTags提供了特殊的方法,对于SELECT标签初始化,从一堆数据里面,并且让一个或者多个选项被选中:

1)from_list(data):返回SELECT标签,用OPTION标签,从数据中。每一个OPTION标签具有条目的值作为内容并且条目在列表中作为值排列着:

s = SELECT().from_list(["foo","bar"])   ==>

 

<SELECT> 

<OPTION value="0">foo 

<OPTION value="1">bar 

</SELECT>

2)select(content=item)或者select(value=item):标记选项,用指定的内容或者值作为已经被选择的了,并且其他的选项没有被选择。item可以是一个内容的列表或者是值,对于具有MULTIPLE选项的SELECT标签有

s.select(content="bar")   ==>

 

<SELECT> 

<OPTION value="0">foo 

<OPTION value="1" SELECTED>bar 

</SELECT>

对于checkbox和radiobuttons,HTMLTags提供了两个类,CHEKCBOX和RADIO.这两个类的实例被一个列表初始化,作为第一个参数,并且INPUT标签的属性作为其他的关键词参数:

radio = RADIO(["foo","bar"],Class="menu")

在RADIO实例的元组(conteng, tag)中迭代,content是普通列表的条目:

for (content,tag) in radio:

    print content,tag

  ==>

foo<INPUT Type="radio" Class="menu" value="0"> 

bar<INPUT Type="radio" Class="menu" value="1">

当实例创建一个后,所有的INPUT标签都是unchecked。check(content=item)方法或者check(value=item)被用来check这些INPUT标签,根据指定的内容或值

radio.check(content="foo")

table = TABLE()

for (content,tag) in radio:

    table <= TR(TD(content)+TD(tag))

print table

  ==>

<TABLE>

<TR>

<TD>foo</TD>

<TD><INPUT Type="radio" Class="menu" value="0"></TD>

</TR>

<TR>

<TD>bar</TD>

<TD><INPUT Type="radio" Class="menu" value="1"></TD>

</TR>

</TABLE>

作为SELECT,item可以是内容列表或者值,说不定一些checkboxes必须被checked

5.6 Unicode

Tags的内容和属性值可以是bytestring或者unicode strings.当一个标签被打印的时候,unicode strings被编码为bytestrings。编码可以通过函数set_encoding(encoding)来定义

如果你没有指定一个编码,系统默认的编码(sys.getdefaultencoding())被使用

在一个Karrigell脚本中,编码通过SET_UNICODE_OUT()定义,也被HTMLTags使用-你不需要使用set_encoding()

 

7.6 模板引擎的集成

对于那些熟悉模板引擎的来说,karrigell让他们集成的非常直接。通过内联函数三种引擎是可用的,其他的可以被使用像是在普通的python脚本中

7.6.1 python string substitution python字符串代换

警告:PythonStringSubst被KT取代,在下一个发布版本中将会被丢弃

这个模板系统使用字符串代换声明,在python2.4中介绍的。模板文件使用$foo形式的占位符

为了在脚本中使用,使用内联函数PythonStringSubst(url, arg1=val1, arg2=val2...):它会获取源字符串,来自文件爱你,在指定的url上,并且应用关键字参数到这个源字符串中

举例,假设模板源码为

<HTML>

<HEAD><TITLE>$title</TITLE></HEAD>

<BODY>

$contents

</BODY>

</HTML>

那么结果为

print PythonStringSubst(src_url,

    title='Python String Substitution', contents='Hello World example'

    )

将会生成

<HTML>

<HEAD><TITLE>Python String Substitution</TITLE></HEAD>

<BODY>

Hello World example

</BODY>

</HTML>

6.2 KT-Karrigell Templates

内联KT函数替代了PythonStringSubst。另外对于字符串代换,KT提供了一个机制,为了包括其他的模板并指定转换的字符串,对了那些被传送给Karrigell翻译引擎的。

KT模板存储在文本文档.kt中。转换已经存在的PythonStringSubst模板是很简单的:

1)改变文件后缀名为.kt

2)把所有的PythonStringSubst改为KT,在Python中和ks脚本中

6.3 Cheetah

如果可以使用cheetah模板,你可以使用上面同样的方法,使用内联函数Cheetah(url, arg1=val1, arg2=val2...).url是模板的url,关键词参数被用来产生HTML代码

6.4 Other engines

为了使用其它的引擎,你必须应用它的声明到脚本中。尽管实现细节多种多样,你的代码可能会看起来像这样子:

import Template # or raise Exception

# get template source from file

templateDef = open(template_file_name).read()

# apply keywords to the template definition and print the result

print Template(templateDef,arg1=val1,arg2=val2, ...)

 

7.7 KT-Karrigell Templates

KT是一个简单的模板引擎,为了使用Karrigell Service(.ks)脚本和Python脚本。KT的目标是:

提供一个简单的模板系统,没有编程控制(逻辑和循环等)

支持内联Karrrigell翻译系统

支持变量替换

支持包含其他模板

7.1 KT模板语言语法

KT模板被保存为以.ks为后缀名的文本文档。语言使用下面的标签,与其他文本混合,尤其是HTML。

包含标签

@[template_url]

包含了由template_url指定的模板。URLs由同样的方式处理,他们在Import()中被处理。支持相关路径,并且与父模板相关。包含被递归的处理,因此子模板可以包含其他模板

代换标签

$identifier

$object.attribute

$dictionary.key

用它的值代换一个标识符。标识符可以是一个简单的名字或者是一个对象或者是一个字典。如果使用了字典,关键字必须是python标识符的有效形式

转换标签

_[string to translate]

使用内联的Karrigell转换系统转换字符串。这相当于.ks和python脚本中的_()函数,也相当于PIH中的<%_ %>

连接标签

@[$identifier]

_[$identifier]

通过设置标识符的值为一个模板的URL,调用脚本来控制包含动作。$object.attrribute和$dictionary.key样式也可以被使用。这为包括模板提供了极大的灵活性。举例,一个主模板可以处理一个页面的基本设置,然后不同的子模板通过调用脚本控制。如果一个$identifier没有定义,或者是一个False值,那么没有包含动作执行。这允许调用脚本关闭一个包含行为。

理论上$indentifiers可以被转换标签替换,但是不是必须的。最好在调用脚本中使用_()函数来完成转换。

7.2 在脚本中调用KT

包含在模板中的值以命名参数的形式传递给脚本:

  print KT(template_url, var1=var1, var2=var2, data=dict, row=row, this=THIS, ...)  

模板URL指向了KT模板文件。KT使用与Karrigell导入函数使用本地python scripts的同样的规则。

支持**dict语法

 print KT(template_url, **dict)

为了方便,python内建locals()函数可以被分配给命名参数,使得模板中的本地变量有效:

print KT(template_url, data=locals())

7.3 Processing

模板按照如下的方式处理

1)所有的包含动作被递归的处理,建立起一个统一的模板。$identifiers在@[]标签中被首先扩展。如果$identifier没有被定义或者是一个False值,就不执行包含动作并且没有引发error。这允许调用脚本关闭包含动作。循环引用会被检查,如果模板尝试包含自己将会引发一个RecurisonError,或者当一个子模板尝试包含它的父模板。

2)所有其他的替代都表现在统一模板中

3)执行转换

7.4 管理转换

转换管理员工具识别kt文件。它自动的在_[]标签中提取要被转换的字符串,以及_()函数和<%_ %>中

7.5 Unicode

KT转换所有的文本为Unicode UTF-8编码,并且返回一个Unicode值

7.6例子

这里有一个KT模板,叫做template/master.kt

<html>

<head>

<link rel="stylesheet" href="$this.baseurl/css/my.css">

<title>MyApp $data.title</title>

</head>

<body>

@[$data.bodytmpl]

<hr>

<i>_[Powered by Karrigell]</i>

<p />

</body>

</html>

注意THIS是怎么传给KT的,并且用来帮助定义URLs到CSS样式表

标签@[$data.bodytmp1]包含了另外的模板,名字由标识符$data.bodytmp1控制。在这个例子中,我们将要设置$data.bodytmp1的值到inde.kt中

index.kt包含了代码

<h1>Welcome to $data.who home page!<h1>

这个代码片段显示了模板如何从一个Ks脚本中调用的,脚本是/myapp.ks

def index():

    SET_UNICODE_OUT("utf-8")

    title = ' -  home'

    who = 'my'

    bodytmpl = 'index.kt'

    print KT('template/master.kt', data=locals(), this=THIS)

如果用户的浏览器被设置为英文,调用/myapp.kt/index将会产生下面的代码

<html>

<head>

<link rel="stylesheet" href="/css/my.css">

<title>MyApp - home</title>

</head>

<body>

<h1>Welcome to my home page!</h1>

<hr>

<i>Powered by Karrigell</i>

<p />

</body>

</html>

如果浏览器的语言时法语,并且转换定义在Karrigell管理员工具中,结果将是

<html>

<head>

<link rel="stylesheet" href="/css/my.css">

<title>MyApp - home</title>

</head>

<body>

<h1>Welcome to my home page!</h1>

<hr>

<i>Motoris?? par Karrigell</i>

<p />

</body>

</html>

 类似资料: