Karrigell是一个开源的Web开发框架。
这个入门指南向我们展示如何创建一个简单的web应用程序:这个例子是一个CD收藏程序。首页上带有一个访问计时器和登录链接并且显示所有的收藏记录。当用户登录到这个程序后就可以对收藏记录进行添加/编辑/删除操作。
第一步就是安装Karrigell。Download 最新版本的Karrigell,然后解压下载的文件,然后到命令行窗口在解压的目录下执行:Python Karrigell.py,这将会在80端口启动Karrigell自带的web服务器。
如果想让web服务器运行在其它端口:Python Karrigell.py -P 8080
在当前我们先不考虑收藏的CD我们先编写主页。
在Karrigell的webapps目录下新建一个mycds目录,然后使用自己喜欢的文本编辑器保存下面的代码到index.ks
def index():
print "<h1>My CD collection</h1>"
在浏览器中访问:localhost/mycds/index.ks/index
扩展名“ks"(Karrigell Service)意味着这个脚本就是个Python脚本并且其中的一个函数映射着一个URL:在地址index.ks/index里意味着浏览器访问的是index()函数返回的数据。
事实上:
注意在函数index()中的print语句,在Karrigell脚本中,print语句会直接发送语句中的内容到客户端浏览器,这个内容支持HTML代码。
页面计数器将会在主面上显示被访问的次数。我们使用一个文件counter.txt,它用来存贮页面被访问的次数。
def index():
print "<h1>My CD collection</h1>"
try:
visits = int(open('counter.txt').read())
except IOError:
# first visit : the file does not exist
visits = 0
visits += 1
out = open('counter.txt','w')
out.write(str(visits))
out.close()
print "%s visits" %visits
每次刷新页面时,你都会看到访问次数自增1。
一个页面计数器不应该在一个用户重复访问一个相同页面时累加计数。这个需求可以通过标识谁在发送来解决。对于这种情况web编程提供了session管理,并且Karrigell有一个简单的实现可用。
使用内置的Session()函数。
Karrigell脚本运行在一个框架中的命名空间内:在脚本中可以用一些内置的函数,我们使用Session()函数,它可以返回一个对象来标识每个客户端。这个对象是一个普通的Python对象,可以对它设置任何属性。
在这里,为每个客户端我们都为session对象创建一个user属性。如果一个客户端请求访问主页并且他的session对象已经有了一个user属性,计数器将不会再累加了:
def index():
print "<h1>My CD collection</h1>"
try:
visits = int(open('counter.txt').read())
except IOError:
# first visit : the file does not exist
visits = 0
if not hasattr(Session(),"user"):
visits += 1
out = open('counter.txt','w')
out.write(str(visits))
out.close()
Session().user = None # create attribute user
print "%s visits" %visits
这个页面计数器应该放在应用程序的其它地方,因此把它分离出来放在脚本counter.py里:
try:
visits = int(open('counter.txt').read())
except IOError:
# first visit : the file does not exist
visits = 0
if not hasattr(Session(),"user"):
visits += 1
out = open('counter.txt','w')
out.write(str(visits))
out.close()
Session().user = None # create attribute user
print "%s visits" %visits
为了在主页中包含这个脚本,我们修改脚本index.ks:
def index():
print "<h1>My CD collection>/h1>"
Include('../counter.py')
Include()是另一个Karrigell内置的函数:它带有一个脚本地址参数,它会把这个脚本运行的结果插入到当前页面中。
你可能惊奇的发现为什么在脚本名的前面加上”../",尽管counter.py与index.ks在同一目录下。其实这是你在Karrigell中遇到的一个小挑战。“Karrigell Service”使用http://host/folder/script.ks/func_name 的形式被调用。这时当前页面就把当前路径当作根路径,这个页面中的counter.py就被看作为http://host/folder/script.ks/counter.py 其实我们期望的是
http://host/folder/counter.py, 为了得到这个路径,我们必须在相关的URL前加上“../"以跳转到上级目录上去。
为了使counter.py更具通用性,可以给Include()函数传递一个文件名参数:
def index():
print "<h1>My CD collection>/h1>"
Include('../counter.py',counter_file='counter.txt')
在执行的时候Include()函数会把字典参数传给counter.py。现在重写counter.py来接收参数:
try:
visits = int(open(counter_file).read())
except IOError:
# first visit : the file does not exist
visits = 0
if not hasattr(Session(),"user"):
visits += 1
out = open(counter_file,'w')
out.write(str(visits))
out.close()
Session().user = None # create attribute user
print "%s visits" %visits
让我们来为程序添加登录的链接。
def index():
print "<h1>My CD collection</h1>"
print '<a href="login">Login</a><br>'
Include('../counter.py',counter_file='counter.txt')
这个链接引用"login".它是一个基于当前URL的URL:host/records/index.ks/index,因此它指向host/records/index.ks/login它的意思是这个链接将会执行index.ks中的login()函数。
这个函数将会生成HTML表单来要求用户输入登录名和密码,并且提交它们的值到身份认证测试:
def login():
print '<h1>Login</h1>'
print '<form action="check_login" method="post">'
print 'Login <input name="login"><br>'
print 'Password <input type="password" name="passwd"><br>'
print '<input type="submit" value="Ok">'
print '</form>'
表单的”action“属性是check_login,它的意思是将调用index.ks中的check_login()函数。
不同于index()和login()函数,这个函数带有参数:提交的登录名和密码。这些参数必须与表单的input字段名字相同:login和passwd。暂时我们使用一个简单的方式测试用户是否可以登录:
def check_login(login,passwd):
if login=="john" and passwd=="doe":
Session().user = login
print "logged in"
else:
print "try again"
在函数里面,如果测试通过,session对象的user属性将会设置成登录的用户名。
暂时我们得到了测试的结果,在测试后我们应该自动的重定向到主页。HTTP协议提供重定向的机制,在Karrigell中有一个简单直接的实现:一个叫做HTTP_REDIRECTION的异常。
像这样修改check_login()函数:
def check_login(login,passwd):
if login=="john" and passwd=="doe":
Session().user = login
raise HTTP_REDIRECTION,"index"
它的意思是在函数执行后,浏览器重定向到指定的URL,这里是当前脚本的index()函数。
现在我们可以修改主页用登录名来欢迎验证后的用户,并且可以让他登出:
def index():
print "<h1>My CD collection</h1>"
logged = hasattr(Session(),"user") and Session().user is not None
if logged:
print 'Logged in as %s<br>' %Session().user
print '<a href="logout">Logout</a><br>'
else:
print '<a href="login">Login</a><br>'
Include('../counter.py',counter_file='counter.txt')
登出函数仅仅把Session().user设成None并且重定向到主页:
def logout():
Session().user = None
raise HTTP_REDIRECTION,"index"
这种编程方式是基于Karrigell的命名空间:在脚本中可以使用环境变量和一组可以完成大多数任务的内置函数。到现在为止我们涉及到了使用session管理的内置函数Session()及包含脚本的Include()函数和HTTP重定向的异常HTTP_REDIRECTION。
这种Karrigell编程方式非常的简单易懂,因此编写代码和维护都很简单。
当然Karrigell还有一些其它的编程方式(如纯Python代码,CGI,Python Inside HTML,HTML Inside Python),我建议使用"Karrigell Service"方式在一个脚本中组织程序中大多数的逻辑,其它的模块可以使用import或include。
在下一章节中我们将编写代码来管理CD数据库。