Differences between revisions 10 and 38 (spanning 28 versions)
Revision 10 as of 2005-07-13 11:17:14
Size: 16155
Editor: ZoomQuiet
Comment:
Revision 38 as of 2009-12-25 07:13:03
Size: 6348
Editor: localhost
Comment: converted to 1.6 markup
Deletions are marked like this. Additions are marked like this.
Line 4: Line 4:
WukooPy -- 又一个新的webapp架构,它是面向python程序员的,包含了 Karrigell 和 Quixote,大家一起来造这个轮子(LiHui)。
'''
  * ''DragonPy''龙的名字俺也不满意,太俗太没创造性,前两天陪女儿看挪吒,这个名字也不错,孙猴子也成,就是不知道英文怎么写?
  * '''WukooPy''' -- Web usage Keep object of Python '''悟空系统''' -- 哈哈哈!保持对象化的 Web应用! 如何?
::-- ZoomQuiet [[[DateTime(2005-07-13T02:41:38Z)]]]
[[TableOfContents]]
WukooPy
''' -- Web usage Keep object of Python
Line 11: Line 7:
= 现有 Web Application 点评 = '''悟空系统''' -- 保持对象化的 Web应用!
  * 又一个新的webapp架构,它是面向python程序员的,包含了 Karrigell 和 Quixote 以及其它优秀思想!大家一起来造这个轮子吧!
Line 13: Line 10:
::-- ZoomQuiet [<<DateTime(2005-07-13T02:41:38Z)>>]
<<TableOfContents>>

  ||{{attachment:Logo.jpg}}||` `||<<Include(/TouchAuthor)>>||

= 缘起 =
'''现有 Web Application 点评'''
Line 28: Line 32:
= 需求 = == 自我需求 ==
Line 39: Line 43:
== 前题 == == 设定前题 ==
Line 43: Line 47:
=== 一个Hello world模块 === 使用Karrigell的发布方式注意,需将Karrigell发布为KarrigellLib包。即增加__init__.py,放在site_packages下

=== 特性预览 ===
Line 89: Line 95:
    return 图文件     return "图文件"
Line 115: Line 121:
=== sqlobject一段代码 === = 下载 =
Line 117: Line 123:
谈sqlobject的好象不是很多,发一段俺的代码,见识一下sqlobject的必杀绝技 0.11 版发布 [[attachment:WukooPy-0.11.zip]]
Line 119: Line 125:
{{{
from sqlobject import *
__connection__='mysql://root:123@localhost:3306/bm'

class UserMark(SQLObject):

    class sqlmeta(sqlmeta):

        table = "user_mark"
        idName = "id"
        #style = Style()
        defaultOrder = 'id'
        _cacheValues = True

    username=StringCol(alternateID=True,length=30,notNone=True,default='')
    userpasswd=StringCol(length=20,notNone=True,default='')
    userdisplay=StringCol(length=60,notNone=True,default='')
    #----------------------------------
    ip=StringCol(length=40,notNone=True,default='')
    #----------------------------------
    sex=StringCol(length=2,notNone=True,default='') #本地库表
    email=StringCol(length=60,notNone=True,default='') #本地库表
    qq=StringCol(length=20,notNone=True,default='') #本地库表
    web=StringCol(length=60,notNone=True,default='') #记录ID
    msn=StringCol(length=60,notNone=True,default='') #记录ID
    timeCreate=DateTimeCol(notNone=True,default=now)
    countAccess=IntCol(notNone=True,default=0)
    countReply=IntCol(notNone=True,default=0)
    countSubmit=IntCol(notNone=True,default=0)
    userType=IntCol(notNone=True,default=0)
    userMoney=IntCol(notNone=True,default=0)
    #----------------------------------
    def addUser(cls,user,passwd1,passwd2,email):
        errorchar=['"',"'",'=','?','.','*','&','%','<','>',' ','!']
        try:
            if passwd1<>passwd2:
                raise 'Password is not same'
            for v in errorchar:
                if v in user or v in passwd1:
                    raise 'Error username or password'
            result=cls(username=user,userpasswd=passwd1,email=email)
        except:
            result=None
        return result
    addUser=classmethod(addUser)
    #----------------------------------
    def checkUser(cls,user,passwd):
        try:
            t=cls.byUsername(user)
            if t.userpasswd==passwd:
                result=t
            else:
                result=None
        except:
            result=None
        return result
    checkUser=classmethod(checkUser)
#----------------init db--------------
DBDict={
    'UserMark':'UserMark',
    }
def proxyDB(tname):
    return globals()[tname]
def clearDB():
    for k,v in DBDict.items():
        proxyDB(v).dropTable(True)
        proxyDB(v).createTable()

if __name__=='__main__':
    clearDB()
}}}
0.10 版发布 [[attachment:WukooPy-0.10.zip]]
Line 192: Line 128:
=== Karrigell 的 quixte 发布 === 支持json,请使用新新的svn版本,感觉是最简单的json发布,不是吹牛。不过可以发送中文,返回的中文编码不知怎么做,熟悉js帮一下先。
[[attachment:wukoopy_testjson.rar]]
Line 194: Line 131:
先发一部分: SVN下载:
Line 196: Line 133:
{{{
#!python
import urlparse
import sys
import os.path
import os
import time
from cStringIO import StringIO
import posixpath
import urllib
import string
http://www.woodpecker.org.cn/svn/woodpecker/WukooPy/trunk/
Line 208: Line 135:
from quixote.publish import Publisher as _Publisher
import quixote.publish
from quixote.http_response import HTTPResponse as _HTTPResponse
from quixote.util import FileStream
from quixote.config import Config
from quixote.http_response import HTTPResponse
from quixote.logger import DefaultLogger
user:woodpecker,pass:[email protected]
Line 217: Line 138:
TRAC访问:
Line 218: Line 140:
#------------------------------------------------------ http://www.woodpecker.org.cn/trac.cgi/browser/WukooPy/trunk/
Line 220: Line 142:
my_k_config=dict(
    initFile='Karrigell.ini',
    PORT=8080,
    protectedDirs=['D:\\pythonMy\\KarrigellLib\\admin'],
    alias={'doc':'D:\\pythonMy\\KarrigellLib/doc','base':'D:\\pythonMy\\KarrigellLib'},
    globalScriptsList=['D:\\pythonMy\\KarrigellLib/myScript1.py','D:\\pythonMy\\KarrigellLib/myScript.py'],
    globalScripts=['myScript1','myScript'],
    extensions_map={'.gif':'image/gif','.jpg':'image/jpeg','.py':'text/html','.nwc':'application/nwc','.html':'text/html','.htm':'text/html'},
    debug=1,
    base='',
    persistentSession=False,
    silent=False,
    language='',
    ignore=['/favicon.ico'],
    serverDir=r'D:\pythonMy\KarrigellLib',
    #rootDir=r'D:\pythonMy\KarrigellLib',
    extensions=['gif','html','nwc','htm','py','jpg'],
    gzip=False,
    )


import KarrigellLib
m=os.path.dirname(os.path.abspath(KarrigellLib.__file__))
if m not in sys.path:
    sys.path.append(m)

msave=sys.argv
sys.argv=[]
import k_config
sys.argv=msave

for k,v in my_k_config.items():
    setattr(k_config,k,v)
k_config.serverDir=os.path.dirname(os.path.abspath(k_config.__file__))
if not k_config.alias.has_key('debugger'):
    k_config.alias['debugger']=os.path.join(k_config.serverDir,'debugger')
if not k_config.alias.has_key('demo'):
    k_config.alias['demo']=os.path.join(k_config.serverDir,'demo')
if not k_config.alias.has_key('fckeditor'):
    k_config.alias['fckeditor']=os.path.join(k_config.serverDir,'fckeditor')
if not k_config.alias.has_key('doc'):
    k_config.alias['doc']=os.path.join(k_config.serverDir,'doc')
if not k_config.alias.has_key('instant_site'):
    k_config.alias['instant_site']=os.path.join(k_config.serverDir,'instant_site')
if not k_config.alias.has_key('components'):
    k_config.alias['components']=os.path.join(k_config.serverDir,'components')
if not k_config.alias.has_key('listDirectory.pih'):
    k_config.alias['listDirectory.pih']=os.path.join(k_config.serverDir,'listDirectory.pih')
if not k_config.alias.has_key('karrigell.css'):
    k_config.alias['karrigell.css']=os.path.join(k_config.serverDir,'karrigell.css')
if not k_config.alias.has_key('admin'):
    k_config.alias['admin']=os.path.join(k_config.serverDir,'admin')



paths=[]
paths.append(os.path.join(k_config.serverDir,'databases'))
for v in paths:
    if v not in sys.path:
        sys.path.append(v)


import SimpleHTTPServer, KarrigellRequestHandler, URLResolution,Template



def translate_path(path):
    """Overrides SimpleHTTPServer's translate_path to handle aliases
    Returns the path to a file name"""
    path = posixpath.normpath(urllib.unquote(path))
    path = path[len(k_config.base):] # remove base beginning the url
    words = path.split('/')
    words = filter(None, words)
    # for ks scripts, path ends at the word ending with "ks"
    w1,w2=[],[]
    for i,word in enumerate(words):
        w1.append(word)
        if word.lower().endswith(".ks"):
            w2=words[i+1:]
            break
    words=w1
    m=words[-1]
    if m.endswith('.html') and '_' in m:
        words[-1]=m.split('_',1)[0]
    if words and words[0] in k_config.alias.keys():
        path=posixpath.normpath(k_config.alias[words[0]])
        path=os.path.join(k_config.alias[words[0]],string.join(words[1:],"/"))
    else:
        path=os.path.join(k_config.rootDir,string.join(words,"/"))
    return path

def list_directory(path,dirName):
    script = Template.getScript(os.path.join(k_config.serverDir,'listDirectory.pih'))
    return script.render({'path':path,'dirName':dirName}).value

setattr(Template,'list_directory',list_directory)
setattr(URLResolution,'translate_path',translate_path)




class QuixoteHandler(KarrigellRequestHandler.KarrigellRequestHandler,SimpleHTTPServer.SimpleHTTPRequestHandler):
    def __init__(self, request):
        self.response_status=(200,'OK')
        self.response_headers=[]
        self.request = request
        self.wfile = StringIO()
        fs=request.get_fields()
        self.headers=dict(request.environ.items())
        for item in self.headers.keys():
            if item.startswith("HTTP_"):
                hd=item[5:]
                self.headers[hd.lower()]=self.headers[item]
        self.command = self.headers['REQUEST_METHOD']
        self.body = {}
        if self.command == 'POST':
            self.body=fs
        self.client_address=(self.headers["REMOTE_ADDR"],0)
        self.path=self.path_without_qs=self.headers["PATH_INFO"]
        if self.headers.has_key("QUERY_STRING"):
            self.path+="?"+self.headers["QUERY_STRING"]
        self.request_version=self.headers["SERVER_PROTOCOL"]
        self.requestline="%s %s %s" %(self.headers["SERVER_PROTOCOL"],
            self.headers["REQUEST_METHOD"],self.path)
        try:
            self.handle_data()
        finally:
            sys.exc_traceback = None # Help garbage collection

    def send_response(self,status, reason=None):
        self.response_status=(status, reason)
    def send_header(self,key,value):
        self.response_headers.append((key,value))
    def end_headers(self):
        pass



class Publisher(_Publisher):

    def __init__(self, root_directory, logger=None, session_manager=None,config=None, **kwargs):
        if config is None:
            self.config = Config(**kwargs)
        else:
            if kwargs:
                raise ValueError("cannot provide both 'config' object and"
                                 " config arguments")
            self.config = config
        for k in my_k_config.keys():
            if hasattr(self.config,k.lower()):
                setattr(k_config,k,getattr(self.config,k.lower()))
        if logger is None:
            self.logger = DefaultLogger(error_log=self.config.error_log,
                                        access_log=self.config.access_log,
                                        error_email=self.config.error_email)
        else:
            self.logger = logger
        if session_manager is not None:
            self.session_manager = session_manager
        else:
            from quixote.session import NullSessionManager
            self.session_manager = NullSessionManager()

        if quixote.publish._publisher is not None:
            raise RuntimeError, "only one instance of Publisher allowed"
        quixote.publish._publisher = self

        self.root_directory = root_directory
        if hasattr(root_directory,'__file__'):
            k_config.rootDir=os.path.dirname(os.path.abspath(root_directory.__file__))
        self._request = None


    def try_publish(self, request):
        self.start_request()
        path = request.get_environ('PATH_INFO', '')
        assert path[:1] == '/'
        # split path into components
        path = path[1:].split('/')
        t=QuixoteHandler(request)
        request.response.set_status(t.response_status[0])
        for v in t.response_headers:
            request.response.set_header(v[0],v[1])
        output = t.wfile.getvalue()
        # The callable ran OK, commit any changes to the session
        self.finish_successful_request()
        return output

}}}
= 快速体验 =
<<Include(WukooPyQuickInto)>>
= 反馈 =
'''有什么体验?'''

WukooPy -- Web usage Keep object of Python

悟空系统 -- 保持对象化的 Web应用!

  • 又一个新的webapp架构,它是面向python程序员的,包含了 Karrigell 和 Quixote 以及其它优秀思想!大家一起来造这个轮子吧!

::-- ZoomQuiet [2005-07-13 02:41:38]

缘起

现有 Web Application 点评 这么多Web Application,到底用什么好啊

俺以前一直用zope,后来感觉是越来越差,原因与Quixote和Cherrypy的作者差不多,网上有他们的文章,俺这里就不说了。后来找啊找啊,前前后后重点试过Quixote、Cherrypy、Karrigell,感觉都还不错,各有各的特点:

  1. Cherrypy:
    • 将对象机制引入web开发,完全的面向对象发布机制,底层数据、api函数使用cpg集中管理。缺点是底层api调用代码老在变,天啊,俺真的受不了,以前做了一个cherrypy小应用,前前后后重构了10来遍,每次只要用svn更新一下cherrypy代码,就得改一次俺的应用代码。俺就搞不明白,比如一个调用session,就用cpg.sessions就成了吧,为什么一会儿这个样式,一会儿另外个样式。
  2. Quixote:
    • 不错,发布方式多,代码结构好,质量最佳,基本上没什么BUG。只是语法调用有点怪异,适应了半天,最后还是不适应。
  3. Karrigell:
    • 最易用的系统,入门真简便,良好的debug框架,动态载入。只是代码结构不好,做个应用就得将Karrigell移过去。再有url不支持定制,太有局限性,比如我动态生成一个js文件,总不能扩展名是个py,hip...吧,而且作者象俺有点不务正业,不老老实实做好框架,却去设计什么dbstrange,还做了一堆没用的半成品,唉,有这功夫把自留地种好啊。感觉做做原型、快速开发还不错。
  4. PS:这两天谈的比较多的是ruby的web架构,不太感冒,这东东也就是让java程序员见识一下:哦,这么这么简单啊,其实不用编码的框架是不存在的,功能实现与编码量本身就是一对对头。

自我需求

见识了这么多框架,俺理想的架构长得模样也自然产生了(主要性能):

  1. 具有多多的发布接口,象Quixote,就是俺以前提过的万能接口,接口越多,余地越大啊。
  2. 底层API与数据的集中管理与调用。比如dgn.get_request(),dgn.get_reponse(),这里的特性是Quixote与Cherrypy的结合和升华。
  3. 简便的发布方式。考虑web前端部份的python代码是最易变的,尽可能简单,易读。利用所有都是对象的性能,选择函数发布。
  4. 支持url定制,易url的default性能。这个需求好象现在很重要,总比使用apache的mod_write好多了。
  5. 语法规则分离出来,用户可使用内置规则,也可定制自已的。内置:quixote_publish1,quixote_publish2,karrigell和函数发布
  6. 方便的角色、权限定义和管理

设定前题

系统使用Karrigell和Quixote代码,对于这两个系统的补丁修改,一律使用动态修正方式偷梁换柱,不改变系统的任何代码,以满足原系统的升级和版权等要求。

使用Karrigell的发布方式注意,需将Karrigell发布为KarrigellLib包。即增加init.py,放在site_packages下

特性预览

还是用一个简便例子说明:

   1 #--系统函数--
   2 def _charsetGB2312(fn):
   3     '''函数包装函数,将页面设为gb2312'''
   4     def _init(dgn,*args):
   5         dgn.set_charset('gb2312')
   6         return fn(dgn,*args)
   7     return _init
   8 def _baseAuth(dgn,func,realm='Protected'):
   9     '''权限函数,只有我能上'''
  10     t=dgn.get_baseauth()
  11     if t is not  None and t==('lihui','password'):
  12         result=None
  13     else:
  14         dgn.set_status(401)
  15         dgn.set_header('WWW-Authenticate', 'Basic realm="%s"' % realm)
  16         result=True
  17     return result
  18 #--web前端--
  19 def helloworld1(dgn):
  20     '''发布一个函数,dgn为数据api集中调用入口,为第一个参数,dgn使用的singlon模式,除系统内置定义外,可自行加入定义,比如dbpool,可定义为dgn.db.dbpool
  21 '''
  22     return 'helloworld1'
  23 
  24 def helloworld2(dgn):
  25     '''发布一个函数,加个权限'''
  26     return 'helloworld1'
  27 helloworld2._q_access=_baseAuth
  28 
  29 def helloworld3(dgn):
  30     '''发布一个函数,gb2312发布'''
  31     return 'helloworld1'
  32 helloworld3=_charsetGB2312(helloworld3)
  33 
  34 def helloworld4(dgn,*args):
  35     '''有args的支持default,比如这个函数url为http:/***/p,这个http:/***/p/1/1/1.html,则转为args=['1','1','1.html']'''
  36     return 'helloworld1'
  37 
  38 def helloworld5(dgn):
  39     '''发布一个图形文件'''
  40     return "图文件"
  41 
  42 
  43 def images(dgn,*args):
  44     '''发布images子目录,静态目录'''
  45     return dgn.StaticDirectory(os.path.join(dgn.get_config().path_top,'images'),*args)
  46 
  47 #--发布函数
  48 def root():
  49     result=helloworld1
  50     result.images=images
  51     result.hl2=helloworld2
  52     result.hl3=helloworld3
  53     result.hl4=helloworld4
  54     result.hl5_jpg=helloworld5  #扩展名为jpg
  55     return result

网站架构组合

原来一直用的是zope的zpt和dtml,cherrytemplate是两者的混合,使用很方便,模块就选它拉

sqlobject真不错,实行了关系数据库+逻辑+对象处理,zodb和存储过程俺再也不用拉。

俺的最佳组合就是dragon+cherrytemplate+sqlobject

下载

0.11 版发布 WukooPy-0.11.zip

0.10 版发布 WukooPy-0.10.zip

支持json,请使用新新的svn版本,感觉是最简单的json发布,不是吹牛。不过可以发送中文,返回的中文编码不知怎么做,熟悉js帮一下先。 wukoopy_testjson.rar

SVN下载:

http://www.woodpecker.org.cn/svn/woodpecker/WukooPy/trunk/

user:woodpecker,pass:[email protected]

TRAC访问:

http://www.woodpecker.org.cn/trac.cgi/browser/WukooPy/trunk/

快速体验

如何利用 WukooPy 进行Web 发布 ::-- ZoomQuiet [2005-07-16 07:05:19]

建立一个wukoo_helloworld包

所有应用项目均以python包方式发布,在这里建立python包的方法很多,不再详述。用于测试,比较偷赖的方法是:

1)在系统site-packages子目录下建立wukoo_helloworld子目录

2)在wukoo_helloworld下建立一个init.py

这样我们就建立了一个wukoo_helloworld包,下面如不特指,一切操作均在wukoo_helloworld子目录下进行

建立项目

建立发布内容

增加一个helloword.py文件,内容:

   1 def helloworld(wkp):
   2     return 'Hello World'

这样我们就做了一个函数发布的页面,页面内容为Hello World,wkp参数为api调用入口

制作页面发布接口

建立发布内容后,就要建立url调用逻辑,这种系统指定使用一个root函数,修改文件为

   1 def helloworld(wkp):
   2     return 'Hello World'
   3 
   4 def root():
   5     result=helloworld
   6     return result

制作项目发布接口

每个项目均应制作一个内容发布接口函数create_publisher,该函数调用不用的语法规则(使用不用的publisher),上页内容增加为:

   1 def helloworld(wkp):
   2     return 'Hello World'
   3 
   4 def root():
   5     result=helloworld
   6     return result
   7 
   8 from wukoopy.publish_wukoopy import Publisher ##使用publish_wukoopy发布
   9 def create_publisher():
  10     return Publisher(
  11         root
  12         )

wukoopy下内置quixote1,quixote2,wukoopy,karrigell四种发布方式,Publisher 参数为:

第一个参数:项目入口,每种publisher的入口形式均不一样,wukoopy为root函数

session_manager:为使用sessions,不加则不使用

config:配置文件

logger:log记录

**kwargs :其它配置

到此我们的项目基本做完了

选择不同方式发布

在wukoo.server下有不同的server发布方式

1)选择simple方式

(1)在命令行下执行

python \*\*\simple_server.py --factory wukoo_helloworld.helloworld.create_publisher

(2)使用python程序

建立一个run_simple.py文件,内容

   1 from wukoo_helloworld.helloworld import create_publisher
   2 from wukoopy.server.simple_server import run
   3 run(create_publisher)

运行后,访问http://localhost:8080/

2)选择cgi访问

建立一个run_cgi.cgi文件,并放在apache可以访问的地方

   1 from wukoo_helloworld.helloworld import create_publisher
   2 from wukoopy.server.cgi_server import run
   3 run(create_publisher)

3)选择fast cgi访问

建立一个run_cgi.fcgi文件,并放在apache可以访问的地方(apache配置不详述)

   1 from wukoo_helloworld.helloworld import create_publisher
   2 from wukoopy.server.fastcgi_server import run
   3 run(create_publisher)

4)选择xitami访问

建立一个run_xitami.py文件

   1 from wukoo_helloworld.helloworld import create_publisher
   2 from wukoopy.server.xitami_server import run
   3 run(create_publisher,'helloworld')

5)选择mod_python访问

配置apache.conf

<LocationMatch "^/helloworld(/|$)">
    SetHandler python-program
    PythonHandler wukoopy.server.mod_python_handler
    PythonOption quixote-publisher-factory wukoo_helloworld.helloworld.create_publisher
    PythonInterpreter wukoo_helloworld.helloworld
    PythonDebug On
</LocationMatch>

6)选择scgi方式

(略)

7)server下还用几种发布方式,参照上述进行。(有一些还是半成品,文件名中有todo)

更多特性

加入子页面

增加一个index,初步展示调用api的方法:

   1 def index(wkp):
   2     wkp.set_content_type("text/html")
   3     result="<html><body>"
   4     result+='<a href="/hello">Hello World</a><br><br>'
   5     result+='</body></html>'
   6     return result
   7 
   8 def helloworld(wkp):
   9     return 'Hello World'
  10 
  11 def root():
  12     result=index
  13     result.hello=helloworld
  14     return result

发布一个静态目录

建立一个images子目录,并发布这个目录为/images

   1 def index(wkp):
   2     wkp.set_content_type("text/html")
   3     result="<html><body>"
   4     result+='<a href="/hello">Hello World</a><br><br>'
   5     result+='</body></html>'
   6     return result
   7 
   8 def helloworld(wkp):
   9     return 'Hello World'
  10 
  11 import os.path
  12 def images(dgn,*args):
  13     return dgn.StaticDirectory(os.path.join(os.path.dirname(__file__),'images'),*args)
  14 
  15 def root():
  16     result=index
  17     result.hello=helloworld
  18     result.images=images
  19     return result

发布一个静态文件

在目录下放一个favicon.ico文件,并发布这个favicon,发布为/favicon.ico

   1 def index(wkp):
   2     wkp.set_content_type("text/html")
   3     result="<html><body>"
   4     result+='<a href="/hello">Hello World</a><br><br>'
   5     result+='</body></html>'
   6     return result
   7 
   8 def helloworld(wkp):
   9     return 'Hello World'
  10 
  11 import os.path
  12 def images(wkp,*args):
  13     return wkp.StaticDirectory(os.path.join(os.path.dirname(__file__),'images'),*args)
  14 
  15 def favicon(wkp):
  16     return wkp.StaticFile(os.path.join(os.path.dirname(__file__),'favicon.ico'),mime_type='image/x-icon')
  17 
  18 def root():
  19     result=index
  20     result.hello=helloworld
  21     result.images=images
  22     result.favicon_ico=favicon   #使用扩展名为.ico
  23     return result

动态改态页面属性

增加一个函数包装函数_charsetGB2312,将index改为GB2312发布

   1 def _charsetGB2312(fn):
   2     '''函数包装函数,将页面设为gb2312'''
   3     def _init(dgn,*args):
   4         dgn.set_charset('gb2312')
   5         return fn(dgn,*args)
   6     return _init
   7 
   8 #---------------------
   9 def index(wkp):
  10     wkp.set_content_type("text/html")
  11     result="<html><body>"
  12     result+='<a href="/hello">Hello World</a><br><br>'
  13     result+='</body></html>'
  14     return result
  15 index=_charsetGB2312(index)
  16 
  17 def helloworld(wkp):
  18     return 'Hello World'
  19 
  20 import os.path
  21 def images(wkp,*args):
  22     return wkp.StaticDirectory(os.path.join(os.path.dirname(__file__),'images'),*args)
  23 
  24 def favicon(wkp):
  25     return wkp.StaticFile(os.path.join(os.path.dirname(__file__),'favicon.ico'),mime_type='image/x-icon')
  26 
  27 def root():
  28     result=index
  29     result.hello=helloworld
  30     result.images=images
  31     result.favicon_ico=favicon   #使用扩展名为.ico
  32     return result

使用基本认证,设置页面访问权限

增加一个权限函数_baseAuth,将protect页面设置访问权限

   1 def _charsetGB2312(fn):
   2     '''函数包装函数,将页面设为gb2312'''
   3     def _init(dgn,*args):
   4         dgn.set_charset('gb2312')
   5         return fn(dgn,*args)
   6     return _init
   7 
   8 def _baseAuth(dgn,func,realm='Protected'):
   9     t=dgn.get_baseauth()
  10     if t is not  None and t==('1','1'):
  11         result=None
  12     else:
  13         dgn.set_status(401)
  14         dgn.set_charset('gb2312')
  15         dgn.set_header('WWW-Authenticate', 'Basic realm="%s"' % realm)
  16         result='密码虽然弱智,你还是访问不了'
  17     return result
  18 #---------------------
  19 def index(wkp):
  20     wkp.set_content_type("text/html")
  21     result="<html><body>"
  22     result+='<a href="/hello">Hello World</a><br><br>'
  23     result+='<a href="/protect">你能进来算你牛</a><br><br>'
  24     result+='<a href="http://1:[email protected]:8080/protect">都告诉密码了还能进不来</a><br><br>'
  25     result+='</body></html>'
  26     return result
  27 index=_charsetGB2312(index)
  28 
  29 def helloworld(wkp):
  30     return 'Hello World'
  31 
  32 def protect(wkp):
  33     return '哈哈,你进来了'
  34 protect._q_access=_baseAuth
  35 
  36 import os.path
  37 def images(wkp,*args):
  38     return wkp.StaticDirectory(os.path.join(os.path.dirname(__file__),'images'),*args)
  39 
  40 def favicon(wkp):
  41     return wkp.StaticFile(os.path.join(os.path.dirname(__file__),'favicon.ico'),mime_type='image/x-icon')
  42 
  43 def root():
  44     result=index
  45     result.hello=helloworld
  46     result.images=images
  47     result.protect=protect
  48     result.favicon_ico=favicon   #使用扩展名为.ico
  49     return result

动态构建和发布一个图形

增加msn函数,从远程获得图形文件并以/msn.jpg发布出去

   1 def _charsetGB2312(fn):
   2     '''函数包装函数,将页面设为gb2312'''
   3     def _init(dgn,*args):
   4         dgn.set_charset('gb2312')
   5         return fn(dgn,*args)
   6     return _init
   7 
   8 def _baseAuth(dgn,func,realm='Protected'):
   9     t=dgn.get_baseauth()
  10     if t is not  None and t==('1','1'):
  11         result=None
  12     else:
  13         dgn.set_status(401)
  14         dgn.set_charset('gb2312')
  15         dgn.set_header('WWW-Authenticate', 'Basic realm="%s"' % realm)
  16         result='密码虽然弱智,你还是访问不了'
  17     return result
  18 #---------------------
  19 def index(wkp):
  20     wkp.set_content_type("text/html")
  21     result="<html><body>"
  22     result+='<a href="/hello">Hello World</a><br><br>'
  23     result+='<a href="/protect">你能进来算你牛</a><br><br>'
  24     result+='<a href="http://1:[email protected]:8080/protect">都告诉密码了还能进不来</a><br><br>'
  25     result+='<a href="/msn.jpg">这是俺的msn,zq老大做的,频繁访问他的网站会受不了</a><br><br>'
  26     result+='</body></html>'
  27     return result
  28 index=_charsetGB2312(index)
  29 
  30 def helloworld(wkp):
  31     return 'Hello World'
  32 
  33 def protect(wkp):
  34     return '哈哈,你进来了'
  35 protect._q_access=_baseAuth
  36 
  37 import os.path
  38 def images(wkp,*args):
  39     return wkp.StaticDirectory(os.path.join(os.path.dirname(__file__),'images'),*args)
  40 
  41 def favicon(wkp):
  42     return wkp.StaticFile(os.path.join(os.path.dirname(__file__),'favicon.ico'),mime_type='image/x-icon')
  43 
  44 def msn(wkp):
  45     wkp.set_content_type('image/jpeg')
  46     result=wkp.web.urlget(
  47         'http://wiki.woodpecker.org.cn/moin/WukooPy/TouchAuthor?action=AttachFile&do=get&target=hui5774hot.png'
  48         )
  49     return result
  50 
  51 def root():
  52     result=index
  53     result.hello=helloworld
  54     result.images=images
  55     result.protect=protect
  56     result.favicon_ico=favicon   #使用扩展名为.ico
  57     result.msn_jpg=msn
  58     return result

URL MAP处理

增加urlmap函数,用来作为缺省urlmap的处理函数,很简单,有*args参数即可

   1 def _charsetGB2312(fn):
   2     '''函数包装函数,将页面设为gb2312'''
   3     def _init(dgn,*args):
   4         dgn.set_charset('gb2312')
   5         return fn(dgn,*args)
   6     return _init
   7 
   8 def _baseAuth(dgn,func,realm='Protected'):
   9     t=dgn.get_baseauth()
  10     if t is not  None and t==('1','1'):
  11         result=None
  12     else:
  13         dgn.set_status(401)
  14         dgn.set_charset('gb2312')
  15         dgn.set_header('WWW-Authenticate', 'Basic realm="%s"' % realm)
  16         result='密码虽然弱智,你还是访问不了'
  17     return result
  18 
  19 
  20 #---------------------
  21 def index(wkp):
  22     wkp.set_content_type("text/html")
  23     result="<html><body>"
  24     result+='<a href="/hello">Hello World</a><br><br>'
  25     result+='<a href="/protect">你能进来算你牛</a><br><br>'
  26     result+='<a href="http://1:[email protected]:8080/protect">都告诉密码了还能进不来</a><br><br>'
  27     result+='<a href="/msn.jpg">这是俺的msn,zq老大做的,频繁访问他的网站会受不了</a><br><br>'
  28     result+='<a href="/urlmap/1/1/m/1.html">什么样的垃级,俺都照吃不误</a><br><br>'
  29     result+='</body></html>'
  30     return result
  31 index=_charsetGB2312(index)
  32 
  33 def helloworld(wkp):
  34     return 'Hello World'
  35 
  36 def protect(wkp):
  37     return '哈哈,你进来了'
  38 protect._q_access=_baseAuth
  39 
  40 def urlmap(wkp,*args):
  41     return ''+str(args)+',原来俺吃的是这个'
  42 
  43 
  44 import os.path
  45 def images(wkp,*args):
  46     return wkp.StaticDirectory(os.path.join(os.path.dirname(__file__),'images'),*args)
  47 
  48 def favicon(wkp):
  49     return wkp.StaticFile(os.path.join(os.path.dirname(__file__),'favicon.ico'),mime_type='image/x-icon')
  50 
  51 def msn(wkp):
  52     wkp.set_content_type('image/jpeg')
  53     result=wkp.web.urlget(
  54         'http://wiki.woodpecker.org.cn/moin/WukooPy/TouchAuthor?action=AttachFile&do=get&target=hui5774hot.png'
  55         )
  56     return result
  57 
  58 def root():
  59     result=index
  60     result.hello=helloworld
  61     result.images=images
  62     result.protect=protect
  63     result.urlmap=urlmap
  64     result.favicon_ico=favicon   #使用扩展名为.ico
  65     result.msn_jpg=msn
  66     return result

使用页面变量,设置页面访问权限

增加一个权限函数_formAuth,将formprotect页面设置访问权限

   1 def _charsetGB2312(fn):
   2     '''函数包装函数,将页面设为gb2312'''
   3     def _init(dgn,*args):
   4         dgn.set_charset('gb2312')
   5         return fn(dgn,*args)
   6     return _init
   7 
   8 def _baseAuth(dgn,func,realm='Protected'):
   9     t=dgn.get_baseauth()
  10     if t is not  None and t==('1','1'):
  11         result=None
  12     else:
  13         dgn.set_status(401)
  14         dgn.set_charset('gb2312')
  15         dgn.set_header('WWW-Authenticate', 'Basic realm="%s"' % realm)
  16         result='密码虽然弱智,你还是访问不了'
  17     return result
  18 
  19 def _formAuth(dgn,func):
  20     if dgn.get_form('user')=='王二' and dgn.get_form('password')=='麻子'
  21         result=None
  22     else:
  23         dgn.set_charset('gb2312')
  24         result='只有王二有权进,去求他吧'
  25     return result
  26 
  27 #---------------------
  28 def index(wkp):
  29     wkp.set_content_type("text/html")
  30     result="<html><body>"
  31     result+='<a href="/hello">Hello World</a><br><br>'
  32     result+='<a href="/protect">你能进来算你牛</a><br><br>'
  33     result+='<a href="http://1:[email protected]:8080/protect">都告诉密码了还能进不来</a><br><br>'
  34     result+='<a href="/msn.jpg">这是俺的msn,zq老大做的,频繁访问他的网站会受不了</a><br><br>'
  35     result+='<a href="/urlmap/1/1/m/1.html">什么样的垃级,俺都照吃不误</a><br><br>'
  36     result+='<a href="/form_protect">试试能不能进</a><br><br>'
  37     result+='<a href="/form_protect?user=王二&password=麻子">只有王二才能进</a><br><br>'
  38     result+='</body></html>'
  39     return result
  40 index=_charsetGB2312(index)
  41 
  42 def helloworld(wkp):
  43     return 'Hello World'
  44 
  45 def protect(wkp):
  46     return '哈哈,你进来了'
  47 protect._q_access=_baseAuth
  48 protect=_charsetGB2312(protect)
  49 
  50 def form_protect(wkp):
  51     return '哈哈,我王二麻子进来了'
  52 form_protect._q_access=_formAuth
  53 form_protect=_charsetGB2312(form_protect)
  54 
  55 
  56 def urlmap(wkp,*args):
  57     return ''+str(args)+',原来俺吃的是这个'
  58 
  59 
  60 import os.path
  61 def images(wkp,*args):
  62     return wkp.StaticDirectory(os.path.join(os.path.dirname(__file__),'images'),*args)
  63 
  64 def favicon(wkp):
  65     return wkp.StaticFile(os.path.join(os.path.dirname(__file__),'favicon.ico'),mime_type='image/x-icon')
  66 
  67 def msn(wkp):
  68     wkp.set_content_type('image/jpeg')
  69     result=wkp.web.urlget(
  70         'http://wiki.woodpecker.org.cn/moin/WukooPy/TouchAuthor?action=AttachFile&do=get&target=hui5774hot.png'
  71         )
  72     return result
  73 
  74 def root():
  75     result=index
  76     result.hello=helloworld
  77     result.images=images
  78     result.protect=protect
  79     result.form_protect=form_protect
  80     result.urlmap=urlmap
  81     result.favicon_ico=favicon   #使用扩展名为.ico
  82     result.msn_jpg=msn
  83     return result

暂时到这:)

反馈

有什么体验?

WukooPy (last edited 2009-12-25 07:13:03 by localhost)