HTML Inside Python(PIH)同Python Inside HTML是相反的;它在Python代码中包含HTML代码这要比使用print语句容易一些。 我们可以使用两种方式:
import os
currentDir=os.getcwd()
"Current directory is <b>"+currentDir+"</b>"
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():
print "<tr><td>%s</td><td>%s</td></tr>" %(item,the_smiths[item])
"</table>"
HTMLTags模块为每个有效的标签使用大写字母定义了一个类。为了创建一个HTML块,一般的语法是:
t = TAG(innerHTML, key1=val1,key2=val2,...)
因此输出的结果是:
<TAG key1="val1" key2="val2" ...>innerHTML</TAG>
例如:
print A('bar', href="foo") ==> <A href="foo">bar</A>
与Python关键字(class,type)同名的属性必须首字母大写:
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语句不会生成关标签。
innerHTML参数可以是一个HTML类的实例,因为我们可以这样建造标签:
print B(I('foo')) ==> <B><I>foo</I></B>
HTML的类支持加操作:
print B('bar')+INPUT(name="bar") ==> <B>bar</B><INPUT name="bar">
并且也支持重复操作:
print TH(' ')*3 ==> <TD> </TD><TD> </TD><TD> </TD>
如果我们有一个实例列表,我们不能使用sum(instanceList)来连接items因为sum只能带几个参数。因此我们像这样调用Sum来完成这个工作:
Sum([ TR(TD(i)+TD(i*i)) for i in range(100) ])
上面的代码会生成一个有0-99个正方形列的行。
innerHTML可以是一个字符串,但是我们不能连接一个字符串和一个HTML类实例,像这样:
H1('To be or ' + B('not to be'))
为了实现上面的功能,可以使用TEXT类,它不会生成任何标签:
H1(TEXT('To be or ') + B('not to be'))
一个简单的文档可以这样写:
print HTML( HEAD(TITLE('Test document')) +
BODY(H1('This is a test document')+
TEXT('First line')+BR()+
TEXT('Second line')))
将会产生为:
<HTML>
<HEAD>
<TITLE>Test document</TITLE>
</HEAD>
<BODY>
<H1>This is a test document</H1>
First line
<BR>
Second line
</BODY>
</HTML>
如果文档比较复杂,为了更好的可读性可以先一个一个的创建元素类,然后把它们整个的打印出来。例如:
stylesheet = LINK(rel="Stylesheet",href="doc.css")
header = TITLE('Record collection')+stylesheet
title = H1('My record collection')
rows = Sum ([TR(TD(rec.title,Class="title")+TD(rec.artist,Class="Artist"))
for rec in records])
table = TABLE(TR(TH('Title')+TH('Artist')) + rows)
print HTML(HEAD(header) + BODY(title + table))
在一个脚本中可以通过Karrigell使用Include(url)函数来包含一个静态文件的内容或一个脚本文件的输出,url是那个文件或脚本的地址(也可以使用普通文件的别名)。
当我们想利用已有的页面创建一组页面时这非常有用,在不同的页面中显示不同的内容(例如一个页头和/或页脚)。我们的脚本可以通过这样构建:
Include("authenticationTest.py") # a script testing user authentication
Include("header.htm") # a static file with a title, style sheet etc
(... your script body ...)
Include("footer.py") # a script which will print current date for instance
在运行时,当出现递归引用(脚本包含自己或脚本1包含脚本2而脚本2又包含脚本1)Karrigell会触发RecursionError异常。
在被调用的脚本中定义的变量与调用它的脚本在运行在同一名字空间里。如果调用脚用是:
name="Brian"
print "The life of "
Include("whoseName.py")
whoseName.py的代码是:
print name
我们将看到name变量在调用脚本里是可以使用的。
也可以传递参数到一个被调用的脚本:可以参见个人portal事例的menu脚本。这个脚本带有一个菜单项列表参数和一个匹配的url的列表参数。
它将通过这种方式被包含:
Labels=[...]
Urls=[...]
Include("k_menu.hip",
labels=Labels,
urls=Urls,
targetUrl="index.pih")
参数也可以通过追加在url后的查询字符串来传递:使用Include("/mypath/aScript.pih?data=dummy")aScript.pih中的变量data在当前名字空间里将是可用的。
Session是用来在服务器端内存中保存一个用户从一个页面到另一个页面相关信息的机制。
假设我们在一个网站上发现并想购买两张CD,然后我们在另一个页面上发现了一本书。然后我们会被询问关于住址信息,如果是一个礼物还会发送一个信息,然后可能会问及我们的信用卡号。如果我们确认购买这时就会出现一个页面显示所有的信息。
如果没有sessions这是很难实现的,那我们每次都要传递上一次的信息到一个隐藏的表单字段,这是很难实现的。
有了sessions一切变得非常容易;每个用户都带有一个"session identifer"标识每次向服务发送请求时都会在表单下附加一个cookie。这个标识符匹配服务器端的一个对象可以设置或得到它的属性值。
在Karrigell中,在页面中如果要想修改或访问session信息,首先要创建一个session对象:
sessionObj=Session()
如果我们开始了一个会话,Karrigell就会生成一个叫做sessionId的cookie并被发送到web浏览器。在后面的请求浏览器会自动的发送这个cookie并且服务器端也会寻找与之相关的对象。
session对象是一个普通的Python对象,我们可以设置它的属性:
sessionObj.name="John Doe"
在另一个脚本我们可以访问它的值:
name=sessionObj.name
Session对象支持一个close()方法,它会导致session信息丢失。
我们不必显示的关闭一个session,Karrigell会确保不会多于1000个session当第1000个session被创建时它就会清除时间最久的那个session.
在一个HTML文件里创建一个表单然后发送到一个PIH脚本:
<h3>Who are you ?</h3>
<form action="sessionTestBegin.pih">
Name <input name="myname">
<br>First name <input name="firstname">
<br><input type="submit" value="Ok">
</form>
下面的脚本将会通过QUERY或者表单字段变量来得到输入的值,创建一个session对象并且把name和firstname作为这个对象的属性保存起来。
<h3>Begin session</h3>
<%
sessionObj=Session()
sessionObj.name=_myname
sessionObj.firstname=_firstname
print sessionObj.name
%>
<a href="sessionTestFollow.pih">Next...</a>
下一个脚本没有使用查询字符串,但它仍然可以通过session对象来得到信息:
<h3>Session test goes on</h3>
<%
session=Session()
print session.firstname
session.close()
%>
因为上面的脚本关闭了session,如果我们回到上一页然后再一次点击Next...链接我们将会得到一个Python的调用栈告诉我们session没有firstname属性。修改上面的脚本删除或注释session.close()这一行看看会发生什么。
16. Authentication
16.1 Basic HTTP authentication
Karrigell支持基本的HTTP身份验证,一种方式就是通过要求用户名和密码来保护一些文件的访问。服务器在接受到用户输入时会把它保存在全局变量AUTH_USER和AUTH_PASSWORD中。如果用户的输入被验证后服务器就会发送一个页面,如果没有被验证用户就会被要求重新输入用户名和密码,如果用户取消了输入就会看到错误的信息。
在Karrigell中,身份验证是通过Authentication函数来处理的,调用