Karrigell是一个用纯Python写的web框架,它非常简单而且有很多的特性。这个教程将会一步一步的说明如何使用Karrigell编写程序。
使用Karrigell开发是很简单的:
print "Hello, world !"
但是如果你看过它的文档,你可能会对这个玩具能做的事感到惊讶:
更多的信息参见documentation
>python Karrigell.py
使用一个文本编辑器保存如下Python代码到webapps目录hello.py的文件里:
print "hello world !"
然后在web浏览器里键入http://localhost/hello.py查看结果
默认的,Python脚本被渲染成HTML代码。如果想使用纯文本格式可在代码里设置Content-Type头,就像这样:
RESPONSE['Content-Type'] = 'text/plain'
print "hello world !"
这个例子展示Karrigell如何工作的:脚本都运行在一个命名空间内。RESPONSE是这个命名空间里可用的名字,它是一个字典控制着HTTP响应的头。
让我们来看看在提交了一个HTML窗体后如何得到这些信息。新建这些HTML代码片段并保存在hello.htm中
<form action="hello.py">
Say hello to <input name="user">
<input type="submit" value="Ok">
</form>
这个页面显示用户名,并且可以提交到hello.py脚本
这是如何让hello.py打印信息的脚本:
print "Hello, " + _user
内置的Karrigell名字空间在接受到自浏览器发送的数据后会有一个叫_user的变量,它是输入到user字段的字符串值(注意是以下划线开头的,它用来避免与Python的关键字或内置的名字冲突)。
也可以选择使用这样的语法:
print "Hello, " + QUERY['user']
QUERY是一个提交表单的字段名字的字典
如果想在一个站点里标识一个用户,比如需要打印它的名字,最简单的技巧是session管理。Karrigell使用另一个内置的名字一个叫Session()的函数来管理session,它返回一个可以设置任何属性的Python对象。
编辑脚本hello.py :
print "Hello, " + _user
Session().user = _user
print """What would you like to order :
<form action="order.py">
CD <input type="radio" name="type" value="CD">
book <input type="radio" name="type" value="book">
<input type="submit" value="Ok">
</form>"""
在第二行设置session对象的user属性值为_user。Session对象是web浏览器特有的,因此它能保证和持久一个用户可以被其它脚本标识。
例如可以在order.py中使用:
print "Hello %s" %Session().user
print "So you want to order a %s" %_type
身份认证是一个非常常见的任务用来检查一个用户是否有执行一个任务的权限。因此,要求用户需要输入登录名和密码,程序会在数据库里查看登录名/密码是否合法。
改变HTML页面来要求输入一个用户名和密码而不只是一个用户名:
<form action="check.py">
Login <input name="login">
<br>Password <input type="password" name="password">
<input type="submit" value="Ok">
</form>
check.py脚本是这样的:
def is_valid(login,password):
# replace this with a check in the users database
return login == 'login' and password == 'password'
if is_valid(_login,_password):
Session().login = _login
print "Hello %s <br>" %_login
print """What would you like to order :
<form action="order.py">
CD <input type="radio" name="type" value="CD">
book <input type="radio" name="type" value="book">
<input type="submit" value="Ok">
</form>"""
else:
print "Sorry, you are not allowed to access this page"
Session对象有了一个login属性后,就可以在其他脚本里通过测试这个属性来测试用户的合法性了:
if hasattr(Session(),'login'):
(show information for authorized users)
else:
(show information for unlogged visitors)
当然也可以选择使用基本HTTP身份认证:一个要求输入登录名和密码的弹出式窗口。为了达到验证的目的在命名空间里一个叫Authentication()的函数,像这样使用:
def authTest():
(check if AUTH_USER and AUTH_PASSWORD are in the database)
Authentication(authTest,"Authentication test",/
"Sorry, you are not allowed to access this page")
print """What would you like to order :
<form action="order.py">
CD <input type="radio" name="type" value="CD">
book <input type="radio" name="type" value="book">
<input type="submit" value="Ok">
</form>"""
Authentication()带有3个参数:
如果验证成功将会继续执行下面的脚本。
目前我们都是把脚本写在不同的文件里。但是一些比较小的脚本就会变的乏味和难以维护。
我们可以使用Karrigell services:Python脚本的每一个函数匹配一个URL。他必须使用“.ks”扩展名。
改变初始的HTML页面:
<form action="home.ks/check">
Login <input name="login">
<br>Password <input type="password" name="password">
<input type="submit" value="Ok">
</form>
然后在home.ks文件里保存下面的代码:
def check(login,password):
if _is_valid(login,password):
Session().login = login
print "Hello",login,"<br>"
print """What would you like to order :
<form action="order">
CD <input type="radio" name="Type" value="CD">
book <input type="radio" name="Type" value="book">
<input type="submit" value="Ok">
</form>"""
else:
print "Sorry, you are not allowed to access this page"
def order(Type):
if not hasattr(Session(),"login"):
print "Sorry, you are not allowed to access this page"
else:
print "Ok %s, you want to order a %s" %(Session().login,Type)
def _is_valid(login,password):
# replace this with a check in the users database
return login == 'login' and password == 'password'
HTML表单中的“action”值为“home.ks/check”,它的意思是Karrigell会在home.ks脚本里查找check()函数。表单里有字段“login”和“password”那么check函数里必须也有两个同名的参数。
在这个函数里,我们首先测试登录名和密码是否合法,它使用了一个私有的函数“_is_valid()”:“私有”的意思是不能通过URL(这里是home.ks/_is_valid)来访问这个函数。
如果测试成功,这个函数会输出另一个表单并且action为“order”,它匹配这个脚本里的order()函数。表单里有一个叫“Type”的字段,order()函数里同样也有一个叫Type的参数(注意Type是以大写字母开头的,这是为了与Python内置的type区别开来)
到现在为止我们都是在脚本中使用print语句把HTML标签包含在里面以用来处理HTML代码。
如果不喜欢这样,可以使用一个叫做HTMLTags的模块,它像这样:
from HTMLTags import *
print HTML(HEAD(TITLE('test'))+BODY('hello world'))
上面的代码与下面的HTML代码等同
<HTML><HEAD><TITLE>test</TITLE></HEAD><BODY>hello world</BODY></HTML>可以像这样重写home.ks脚本:
from HTMLTags import *
def check(login,password):
if _is_valid(login,password):
Session().login = login
print "Hello",login,"<br>"
print """What would you like to order :"""
print FORM(TEXT('CD')+INPUT(Type="radio",name="Type",value="CD") +
TEXT('book')+INPUT(Type="radio",name="Type",value="book") +
INPUT(Type="submit",value="ok"),
action="order")
else:
print "Sorry, you are not allowed to access this page"
def order(Type):
if not hasattr(Session(),"login"):
print "Sorry, you are not allowed to access this page"
else:
print "Ok %s, you want to order a %s" %(Session().login,Type)
def _is_valid(login,password):
# replace this with a check in the users database
return login == 'login' and password == 'password'
就像PHP那样把代码嵌入在特殊标签内,Karrigell提供“Python Inside HTML”。这样的脚本使用.pih扩展名,它在HTML代码中把Python代码写在<%和%>标签里。
回到我们的获得用户名的脚本示例里,我们把代码写在order.pih脚本里:
Hello, <% print _user
Session().user = _user %>
What would you like to order :
<form action="order.py">
CD <input type="radio" name="type" value="CD">
book <input type="radio" name="type" value="book">
<input type="submit" value="Ok">
</form>
没有严格的规则来选择编写Python脚本的方式,Karrigell services或Python Inside HTML。我趋向于:
8. Redirection
为了在一个脚本中实现HTTP重定向,需要触发一个在命名空间内可用的异常HTTP_REDIRECTION,它带有一个url参数。
raise HTTP_REDIRECTION,"index.html"例如,如果要输入一个新记录到数据库,这是一个简单的ks脚本示例:from HTMLTags import *def index():print FORM(TEXT('login')+INPUT(name="login")+BR()+TEXT('password')+INPUT(name="password")+BR()+INPUT(Type="submit"),action = "insert")def insert(login,password):(... perform insertion in the database here ...)raise HTTP_REDIRECTION,"index"
在插入完成后,程序将会访问另外一个接口。