Karrigell中的脚本样式(Script styles)
分为7节:
1.python scripts
2.karrigell services
3.python inside HTML
4.HTML inside python
5.HTMLTags - generate HTML in Python
6.integration of templationg engines
7.karrigell templates
下面开始一点点介绍
1.python scripts
karrigell中的python脚本就是普通的python脚本,除了print语句之外,print语句会把输出到标准输出的数据重定向到客户端浏览器里面去。因此如果你想得到正确的格式,你将不得不写HTML代码;对于一个最小的表格,你需要写:
print "<TABLE>"
print "<TR>"
print "<TD>Name</TD>"
print "<TD>Address</TD>"
print "</TR>"
print "</TABLE>"
或者呢,可以用多行格式:
print """<TABLE>
<TR>
<TD>Name</TD>
<TD>Address</TD>
</TR>
</TABLE>"""
或者,如果你想要使用HTMLTags模块,可以这样写:
from HTMLTags import *
print TABLE(TR(TD("Name")+TD("Address")))
如果你写的代码不会被karrigell执行(比如他们是有一个GUI的用户界面),你可以把下面的代码放到脚本的前面:
try:
SCRIPT_END
except NameError:
pass
else:
print "This script can't be executed by Karrigell"
raise SCRIPT_END
(... rest of your script here ...)
因为SCRIPT_END是在karrigell的命名空间中的,在这种情况下表示执行结束;当在命令行运行的时候,一个NameError被引发,然后被脚本忽略掉。
2.Karrigell Services
2.1定义
"karrigell services“是Python脚本,可以处理一些URLs,因此一个具有多个HTML页面的完整的服务可以通过一个脚本来创建。它们是用karrigell时最常用的写脚本的方式,为了编程简单(更直接的访问用户的值)和维护(整个应用程序的逻辑在一个脚本中定义)
为了达到这个目的,在karrigell service中每一个定义在模块层的函数匹配一个URL:在dummy.ks中的foo()函数是由dummy.ks/foo来调用的
这使得页之间的传递值非常直接:如果一个页面有一个如下的链接
<A HREF="script.ks/foo?bar=99">
脚本处理值,就要通过把它定义为参数:
def foo(bar):
print bar
表格中的值用同样的方法处理:
<FORM ACTION="script.ks/foo">
<INPUT NAME="bar">
<INPUT TYPE="submit" VALUE="Ok">
和上面一样的脚本将会处理用户输入的值
def foo(bar):
print bar
在函数中定义为参数的名字必须要和链接或者表格中的名字是一样的;函数也可以像普通python脚本中的函数一样定义默认的值,当浏览器没有传值过来时:
def foo(arg1,arg2=None):
print "First argument",arg1
if arg2 is not None:
print "Second argument",arg2
如果没有指定函数,karrigell回去搜索叫做index()的函数,不带任何参数。
注意:为了安全和可读性,只有明确的定义在ks脚本文件中的函数和那些源码中定义在0列的函数可以被调用
2.2 Building applications
为了从一个函数跳转到另一个函数,只需要在链表或者表格中指定函数名字:
def index():
print '<a href="foo?name=bar">go to foo</a>'
def foo(name):
print '<IMG SRC="../picture.jpg">'
print name
注意foo()函数的第一行:因为URL的处理方法,相关的URL对于文件或者脚本,在相同的目录下座位一个ks脚本必须有前缀../
所有的HTTP环境,自定义的异常,认证的函数,会话控制等,都和python脚本相同
2.3 ”Private" functions
如果你需要在脚本里定义函数,但是不想让它被url调用,那么在函数名前加下划线前缀(_)
def _private(value):
"""Private function - can't be called from the outside"""
return value+1
2.4 Example
这里有一个简单的kariigell服务器程序,使用会话管理和HTTP重定向
so = Session()
if not hasattr(so, 'x'):
so.x = 0
def index():
print "x = %s" %so.x
print '<br><a href="increment">Increment</a>'
print '<br><a href="decrement">Decrement</a>'
print '<br><a href="reset">Reset</a>'
def increment():
so.x = _private(so.x)
raise HTTP_REDIRECTION,"index"
def decrement():
so.x -= 1
raise HTTP_REDIRECTION,"index"
def reset():
so.x = 0
raise HTTP_REDIRECTION,"index"
def _private(x):
"""The function name begins with _ : internal function,
can't be call by a url"""
return x+1
3.python inside HTML
python inside HTML表现出来的很像微软的ASP,SUN的JSP和PHP:它基本上就是一个HTML文档,你在里面插入了部分的编程语言代码,这里我们用的是python
在PIH中,这些代码部分被<% %>分隔开
假设你想要显示当前的数据,你需要用下面的方式混合html和python代码?
The current date is
<% import datetime
print datetime.date.today().strftime("%d:%m:%y")
%>
使用文本编辑器,输入上面的代码并保存为time.pih在根目录里保存。访问http://localhost/time.pih看看发生了什么
你可能会注意到<%%>中的代码就是原始的python代码,你可以在里面导入模块,创建并实例化类,使用变量,读写文件等等。访问HTTP变量,表格,Kariigell定义的异常,都用同样的方法,像python脚本一样。
3.1 python variables
当你只想打印一个变量的值,不用<% print var %>你可以使用<%= var%>来代替:
Current directory <%= os.getcwd() %>
在这个例子中,你将会注意到你不需要明确的导入os模块:为了方便,在你执行脚本的时候它已经在命名空间中了;同理strring和cookie模块也是一样,因为它们被用到的几率太高了,如果你写了导入这些模块,代码照样可以很好的运行。
3.2 String转换
因为在karrigell中国际化很重要,这里有一个方便的字符串转换方法来转换用户参数:<%_string%>
<% import time %>
<%_ "Current directory is " %> <%= os.getcwd() %>
<%_ "Current day " %> <%_ time.strftime("%a",time.localtime()) %>
如果你已经准备转换字符串Current directory is,当用户调用这个脚本用法语的时候,它的浏览器将会显示 Le répertoire courant est
相关请参考karrigell的国际化支持
3.3 indentation
处理PIH文件的结果就是python代码;代码必须要缩进。因为一个PIH脚本是一个混合了HTML的文件,HTML对于缩进只是为了易读,同时也混合了python代码块,它很难形成具有易读和正确缩进的代码。
3.3.1 Basics
PIH遵循下面的简单规则:
脚本的开始缩进为0
每一部分的缩进都参考当前的缩进
当前的缩进可以由2中方法来修改:
1.当Python代码由:冒号结尾的时候,跟着的缩进加1
2.使用<% end %>时减少缩进
简单的例子:
# indentation
<% if hour<12: %> # 0 - next one : 1
Good morning # 1
<% end> # 1 - next one : 0
<% elif hour<18: %> # 0 - next one : 1
Good afternoon # 1
<% end> # 1 - next one : 0
<% else: %> # 0 - next one : 1
Good evening # 1
<% end> # 1 - next one : 0
Ladies and Gentlemen # 0
一个循环的例子:
# indentation
<table border=1> # 0
<tr> # 0
<th>Number</th> # 0
<th>Square</th> # 0
</tr> # 0
<% for i in range(10): %> # 0 - next one : 1
<tr> # 1
<td><% print i %></td> # 1
<td><% print i**2 %></td> # 1
</tr> # 1
<% end %> # 1 - next one 0
</table> # 0
不用这个 <% end %>标签,</table>标签将会被插入到loop中
最后一个例子用了2层缩进
# indentation
<% for i in range(10): %> # 0 - next one : 1
<% if i % 2: %> # 1 - next one : 2
<td class="odd"><%= i %></td> # 2
<% end %> # 2 - next one : 1
<% else: %> # 1 - next one : 2
<td class="even"><%= i %></td> # 2
<% end %> # 2 - next one : 1
<% end %> # 1 - next one : 0
End of table # 0
注意到,第一行标签必须用%>结束掉,否则,第二行以后的缩进为1
3.3.3 <indent>标签
对于长的或者是复杂的代码使用<% end %>会变得很无聊。如果你想要代码中的部分像在PIH中一样被缩进,使用<indent>标签
第一个例子:
# indentation
<indent> # 0
<% if hour<12: %> # 0
Good morning # 1
<% elif hour<18: %> # 0
Good afternoon # 1
<% else: %> # 0
Good evening # 1
Ladies and Gentlemen# 0
</indent>
第二个例子:
# indentation
<table border=1> # 0
<tr> # 0
<th>Number</th> # 0
<th>Square</th> # 0
</tr> # 0
<indent> # 0
<% for i in range(10): %> # 0 (A)
<tr> # 1
<td><% print i %></td> # 1
<td><% print i**2 %></td> # 1
</tr> # 1
</indent> # next one : 0
</table> # 0
在有<A>记号的这一行,我们看到行的缩进与<indent>标签相关
同样注意到在</indent>之后的缩进变成了0
一个嵌入循环的例子:
<indent>
<table border=1>
<% for i in ['h']+range(10): %>
<tr>
<% for j in ['h']+range(10): %>
<% if i!='h' and j!='h': %>
<td><%= i*j %></td>
<% elif i!='h': %>
<th><%= i %></th>
<% elif j!='h': %>
<th><%= j %></th>
<% else: %>
<td>*</td>
</tr>
</table>
</indent>
3.4PIH作为一个模板系统
PIH脚本可以用来创建HTML文件,在Karrigell服务器之外,把它们变成一个模板系统
举例,这个HTML文档由PIH脚本产生。章号没有固定,像下面的方式插入:
<h1><%= chapter %>. Python Inside HTML</h1>
为了从PIH脚本产生HTML文件,使用模块Template.py在/karrigell/core下,传递它的PIH文件的路径来创建一个实例,然后应用它的方法render([name_space.[,out]]),传递给它命名空间,可以在里面找到需要的变量和一个具有write()方法的文件对象,(默认是sys.stdout)
import Template
script=Template.Template("pythoninsidehtml.pih")
chapter=5
# run script in global namespace and write result to sys.stdout
script.render(globals())
3.5 调试
出于调试目的,开始PIHapp.py脚本。它是一个小的GUI应用程序,显示了PIH文件如何转换为python脚本。脚本的结果可以被保存为一个HTML文件,显示在浏览器中,如果它没有调用外部的变量。声明被高亮。