Karrigell/主页
目前,我们将忽略 CD 并开始编写主页
创建一个新文件夹mycds在您的 Karrigell 发行版中,位于www文件夹下。使用您喜欢的文本编辑器,将此文本保存到名为index.ks
def index(): print "<h1>My CD collection</h1>"
在您的浏览器中,访问localhost/mycds/index.ks/index
扩展名 "ks" (Karrigell 服务) 表示该脚本是 Python 脚本,其中函数与 URL 匹配:这里,index.ks/index表示该函数index()将把数据发送回浏览器
事实上
- 如果您没有指定函数名,则脚本中的index()函数将被运行,因此您可以访问localhost/mycds/index.ks
- 而且,如果您在一个文件夹中甚至没有指定脚本名,则名为index的脚本将被运行。所以您实际上只需要输入localhost/mycds
请注意print语句在index()函数中。在 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。
请注意,该文件通过通常的open()函数打开;相对路径相对于脚本目录转换为绝对路径。
如果同一个用户反复重新加载同一个页面,页面计数器不应递增。这需要一种识别发送请求的浏览器的方法。为了完成此任务,网页编程提供了会话管理,而 Karrigell 对此概念有非常简单的实现。
使用内置的Session()函数
Karrigell 脚本在由框架准备的命名空间中运行:在脚本中可用的名称中,您拥有此Session()函数,它返回特定于每个单个客户端的对象(它使用 cookie)。此对象是一个普通的 Python 对象,您可以为其设置任何您喜欢的属性。
这里,对于新客户端,我们将为会话对象创建一个名为 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 内置函数:它接受一个脚本 URL 作为参数,并将此脚本执行的结果插入页面。
为了使counter.py更加模块化,文件名可以作为参数传递给为以下内容:。
def index(): print "<h1>My CD collection>/h1>" Include('counter.py',counter_file='counter.txt')
对为以下内容:的关键字参数将在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,这意味着该链接将调用脚本中login()函数的执行。index.ks
此函数将生成一个 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。同样,这意味着check_login()函数将在index.ks中运行。
与index()和login()不同,此函数将接受参数:提交的登录名和密码。参数必须与表单的输入字段中使用的名称相同:login和passwd。目前,我们将使用一个非常简单的测试来查看用户是否被允许登录。
def check_login(login,passwd): if login=="john" and passwd=="doe": Session().user = login print "logged in" else: print "try again"
在此函数内部,如果测试成功,则会话对象的属性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()函数的执行。
匹配的 URL。
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(): del Session().user raise HTTP_REDIRECTION,"index"
并重定向到主页。
总结[编辑 | 编辑源代码]Session()Karrigell 使用的编程风格基于命名空间:在脚本中,不导入模块或使用环境变量,而是提供了一些内置名称供最常见的任务使用。到目前为止,我们已经涵盖了使用内置名称为以下内容:的会话管理,使用HTTP_REDIRECTION
包含脚本,以及使用内置异常
进行 HTTP 重定向。这使得使用 Karrigell 进行编程非常简单,因此易于编码和维护。
虽然有其他格式可用(有关纯 Python 脚本、CGI、Python Inside HTML、HTML Inside Python 的文档,请参阅文档),但我建议使用 "Karrigell 服务" 将大部分应用程序逻辑组合在一个脚本中;外围模块可以被导入或包含。