Python论坛  - 讨论区

标题:[python-chinese] Karrigell 的MVC化

2007年12月17日 星期一 08:48

Zoom.Quiet zoom.quiet在gmail.com
星期一 十二月 17 08:48:46 HKT 2007

感谢 lv yi <lvscar在gmail.com> 的分享!
http://wiki.woodpecker.org.cn/moin/KarrigellStorm

= 装在推车里的暴风雪 =
 * 原始文章:http://bbs.chinaunix.net/thread-1030014-1-1.html ^2007-12-16 23:02 ^

活在这个到处web n.0 的时代,无论工作还是爱好,出个web小项目,这需求对咱程序员实在是太普遍了。
作为python爱好者,你会杂办?
把django资料找出来花个3个月,熟悉它庞大的结构。独特的ORM,和各种taglib ?
哈,俺们又不是可怜的ruby用户。
你完全可以在python世界里信手拈起最适合你的组件,以最快的速度构建起你自己的web框架。

如果你的项目符合以下条件,你或许可以考虑 karrigell + storm


    * 不需要承载海量用户并发访问
    * 快速上手的开发过程
    * 需要高可读性和易于维护的代码
    * 延续你在java中习惯的mvc思想
    * 使用人性化的ORM进行db操作
    * 简单的部署步骤


== 先是一点背景: ==

=== Karrigell: ===

Karrigell  是轻量级的web框架。灵活,直观,数据库/ORM/模板引擎 独立。

Karrigell 很容易上手,花个1小时把tutorial一看,就能用html和python代码拼出个简单的web程序出来。

Karrigell 支持多种方式混合python代码和html。无论你以前有哪一派的背静,都能在karrigell里延续你的经验和习惯。

Karrigell 部署简单。有python运行环境,就能让它跑的欢畅。

Karrigell代码成熟。 5年来Karrigell基本保持着半年一个版本速度在成长。


=== Storm   ===

Storm 是由Canonical开发的一套 Python ORM库,用在支持着ubunut的Launchpad项目上。

以下是Storm的一些亮点(翻译自storm官方网站):

干净的轻量级API使得Storm的学习上手过程相对轻松。基于Storm的代码也有着友好的维护性.

Storm由测试驱动模式开发,任何一行没经过测试的代码都被认为存在bug。

Storm 中的Model类 不需要特别的构造器,也不需要强制使用专门的基类。

Storm 整体设计得很好。 (代码中不同的部分有着非常清晰的边界。公共api数量小和意义明确)

Storm从一开始以同时支持轻量级(SQLite)和重量级(PostgreSQL / MYSQL)而设计。

Storm代码遵循KISS原则编写,代码简单易读,调试方便。

Storm从一开始就为着同时支持低端小程序和高端(多个数据库,十亿级数据量)而设计。

=== 相关学习资料 ===
karrigell和storm 都很pythonic,看完toturial 基本就能上手.
想深入了解就直接看代码。代码均干净整洁,注释详尽。看这类项目的码是享受啊:

 * karrigell的toturial地址:http://karrigell.sourceforge.net/en/front.htm
 * ChumpKlutz 朽木兄对这这份toturial进行了翻,可以到他的blog 查看:http://blog.csdn.net/chumpklutz/

 * storm的toturial地址:https://storm.canonical.com/Tutorial
  * 目前还没有中文版,俺争取下月完成这份toturial的翻译.


== 对Karrigell的MVC化规范 ==
karrigell 附带的demo是学习karrigell最好的途径。Karrigell的各种用法都在这七八个demo中有精彩的体现。但或许是作者刻意想通过这几个
demo 体现出karrigell的灵活,phi,hip,ks 混合起来蛮容易把人搞晕。而且附带的几个demo
代码组织都很松散,往往就是把一堆phi,hip,ks,js,gif放在一起了事。如果之前看过rails或django
可能会不太适应karrigell demo中的这种凌乱感。

哈,别慌,如果愿意,你完全可以把你的项目按照天条似的mvc结构来组织。加上少许规范,karrigell也能秀出rails那样的形式主义美。

下面是,我的一个小项目的
=== 代码安排: ===
在 karrigell webapps 目录下,用你喜欢的名字命名你的karrigell工程。
工程目录下,新建:{{{
conf/  control/   model/  service/  test/  util/  web/  这几个目录,
以及 index.pih   和 __init__.py
}}}
我的习惯是把`目录恒量`,和数据库配置放在 conf 下。
 * ORM 对象 放在 model 目录;
 * service目录下放置业务代码;
 * util里放入第三方库;
 * test里写点小测试代码。
 * 所有前台代码,都放到web目录里,所以web目录下可以再新建几个js/ css/ uploadFiles/  这样的目录。
  * web目录下,只写和前台展现相关的代码,根据页面的复杂程度,在pih和hip中选择。
 * contorl目录下,只写页面跳转,为web目录下的pih和hip提供变量 和调用相关业务方法的代码。 ks是最好的选择。
同一个对象,不同的web行为。可以写在成一个ks中的多个方法。

 tips:: ks 中不能直接捕获引入方法抛出的异常,因为异常在 core.k_script  里已经被捕获并做了处理。
我的解决方法是,把所有自己用到的异常的自定义父类 添加到
core/k_script.py 154行左右  直接抛出捕获异常的 except 字句参数里。
然后再把所有用到的异常引入 modules/mod_ks.py 中。


=== 集成Storm: ===
karrigell 集成storm可以说是非常方便。 把storm 解压后,放到 karrigell的 /databases 目录。
在我们的项目的 conf/ 目录下 建立个storm_conf.py 的module 内容如下:
{{{#!python
fromdatabases.storm.locals import *
db_url = "postgres://lvs:car@localhost/digyn_dev"

database = None
store = None
def getStore():
    global store
    if store == None:
        store = Store(getDatabase())

    return store


def getDatabase():
    global database
    if database == None:
        database = create_database(db_url)
    return database

#因为采用了module 全局变量。引用此module在最好统一为绝对包名引用
}}}

然后,我们就可以在service里 像这样自然的进行数据的持久化操作:
{{{#!python
from webapps.digyn.model.orm_models import *
from webapps.digyn.util.pager import Pager
from webapps.digyn.conf import storm_conf
store = storm_conf.getStore()
def add(moduleId,title,bugInfo,findDate,findUserId):
    bug = Bug(moduleId,title,findDate,findUserId,bugInfo)
    bug.bug_state = constantValue.bugState_new
    store.add(bug)
    store.commit()
    return bug.id

def get(bugId):
    return store.get(Bug,bugId)

def getBugsPagerForModule(moduleId,bugState,pageNumber=1,pageSize=10):
    """获取特定模块下特定状态的bug"""
    resList = store.find(Bug,Bug.module_id == moduleId,Bug.bug_state
== bugState).order_by(Bug.id)
    presList = resList[(pageNumber-1)*pageSize:pageNumber*pageSize]
    return Pager(presList,pageNumber,pageSize,resList.count())

}}}
[ 本帖最后由 lvscar 于 2007-12-17 01:12 编辑 ]

=== 后台到前台的代码片段 ===

从后台到前台实现用户管理功能的代码片段:

storm ORM 对象  `orm_models.py:`
{{{!python
import md5
from databases.storm.locals import *

class User(Storm):
    __storm_table__='users'
    id = Int(primary=True)
    password =  RawStr()
    name = Unicode()
    info = Unicode()
    is_admin = Bool()
    manageProjects = ReferenceSet('User.id','Project.manager_id')
    joinProjects =
ReferenceSet(id,'_UserProjectRelation.user_id','_UserProjectRelation.project_id','Project.id')
    joinModules =
ReferenceSet(id,'_UserModuleRelation.user_id','_UserModuleRelation.module_id','Module.id')

    def __init__(self,name,password,is_admin=False):
        self.name = name
        self.password = password
        self.is_admin = is_admin

    def __setattr__(self,name,value):
        if name == 'password':
            #self.__dict__['password'] = value   #设值是通过Storm
属性类的__set__方法(重载 '='操作符 )实现的。改变instance中的值,变化不会被storm察觉
            processedPassword = md5.new(value).digest()
            User.password.__set__(self,processedPassword)
        else:
            super(User,self).__setattr__(name,value)
}}}

虽说 Storm orm对象不需要继承特别的父类,但继承Storm类会带来一个方便,
在建立对象关系时,可以用字符串引用其他类。

Service层代码:`userService.py:`
{{{#!python
import md5
from webapps.digyn.conf import storm_conf
from common.exception import *
from webapps.digyn.model.orm_models import User
from webapps.digyn.util.pager import Pager

store = storm_conf.getStore()

def addUser(name,password):
    if checkUserNameUsed(name):
        raise NameDuplicate, name
    user = User(name,password)
    store.add(user)
    store.commit()

def checkUserNameUsed(name):
    if store.find(User,User.name == name).one():
        return True
    else:
        return False

def deleteUser(userId):
    user = get(userId)
    store.remove(user)
    store.commit()

def loginValidate(name,password):
    password = md5.new(password).digest()
    user = store.find(User,User.name == name,User.password == password).one()
    if user:
        return user
    else:
        return False
def get(userId):
    return store.get(User,int(userId))

def getAllUser():
    return store.find(User)

def getManageProjects(userId):

    user = store.get(User,int(userId))
    projectList = []
    for p in user.manageProjects:
        projectList.append(p)
    return projectList

def getjoinProjects(userId):
    user = store.get(User,int(userId))
    projectList = []
    for p in user.joinProjects:
        projectList.append(p)
    return projectList
def assignAdmin(act,userId):
    user = get(userId)
    if act == 'add':
        user.is_admin = True
    elif act == 'remove':
        user.is_admin = False
    store.commit()

def getUserPager(pageNumber =1,nameQueryStr = None,pageSize=10):
        if (nameQueryStr and len(nameQueryStr) > 0):
            resList = store.find(User,User.name.like(u"%"+nameQueryStr+u"%"))
        else:
            resList = store.find(User)
        resList = resList[(pageNumber-1)*pageSize:pageNumber*pageSize]
        return Pager(resList,pageNumber,pageSize,resList.count())
}}}

顶楼那个tips的意义,就在于可以让Service层中写addUser方法时,我们可以直接抛出一个自定意异常,让control层代码可以写成下面这种格式:{{{
     try:
        userService.addUser(name,password)
    except NameDuplicate,userName:
        Include("/digyn/web/user/register.pih",flash="用户 %s 已经存在"
%str(userName))
        return
    Include("/digyn/index.pih",flash="%s 你的帐号已添加,请登录"  % (name.encode('utf-8')))
}}}
[ 本帖最后由 lvscar 于 2007-12-17 00:25 编辑 ]


=== Control层代码 ===
 * `userControl.ks`:
{{{#!python
#-*- coding:utf-8 -*-
from webapps.digyn.service import userService
from common.exception import *
PageSize = 10

def register(name,password,password_again):
    name = unicode(name,'utf-8')
    if(password != password_again):
        Include("/digyn/web/user/register.pih",flash="两次输入的密码不符")
        return
    try:
        userService.addUser(name,password)
    except NameDuplicate,userName:
        Include("/digyn/web/user/register.pih",flash="用户 %s 已经存在"
%str(userName))
        return
    Include("/digyn/index.pih",flash="%s 你的帐号已添加,请登录"  % (name.encode('utf-8')))

def login(name,password):
    name = unicode(name,'utf-8')
    user = userService.loginValidate(name,password)
    if user:
        session = Session()
        session.userId = user.id
        if user.is_admin:
            session.is_admin = True
        else:
            session.is_admin = False
        Include("/digyn/web/user/userIndex.pih",user=user)
        return
    else:
        Include("/digyn/web/user/login.pih" ,flash="该用户不存在或密码错误")

def logout():
    Session().close()
    raise HTTP_REDIRECTION,"/digyn"

def userManage(act,pageNumber=1):
    pageNumber  = int(pageNumber)
    _checkIsAdmin()

    if act == "list":
        _getUserPager(pageNumber)

def _getUserPager(pageNumber ,nameQueryStr = None,pageSize=PageSize):
    userPager = userService.getUserPager(int(pageNumber),pageSize=pageSize)
    Include("/digyn/web/admin/userList.pih",userPager=userPager)

def assignAdmin(act,userId):
    """设定用户是否为系统管理员"""
    _checkIsAdmin()
    userId = int(userId)
    if act == "add":
        userService.assignAdmin("add",userId)
    elif act == "remove":
        userService.assignAdmin("remove",userId)
    else:
        print "erroe"
        return
    print "success"

def deleteUser(userId):
    _checkIsAdmin()
    userId = int(userId)
    userName = userService.get(userId).name
    userService.deleteUser(userId)
    userPager = userService.getUserPager(1,pageSize=pageSize)
    Include("/digyn/web/admin/userList.pih",userPager=userPager,flash="用户
%s 已经删除" %(userName.encode('utf-8')))

def _checkUserLogin():
    if not hasattr(Session(),'userId'):
        Session().close()
        Include("/digyn/web/user/login.pih",flash="请先登录")
        raise SCRIPT_END
def _checkIsAdmin():
    if(( not hasattr(Session(),'is_admin')) or (not Session().is_admin)):
        Session().close()
        Include("/digyn/index.pih",flash="你未被授权访问")
        raise SCRIPT_END
}}}

Control层一个方法对应 一个web动作,表单参数名直接用做方法参数。 通过url来决定调用哪个方法
例如下面的表单实现用户登录:
{{{
用户名
密码
}}} Include 和 raise HTTP_REDIRECTION 这两种实现url转向的方法类似 java servlet编程中的 sendRedirect 和 forward 通过_checkUserLogin /_checkIsAdmin 提高安全性,实现 rails中的 before filter 的效果。 [ 本帖最后由 lvscar 于 2007-12-17 00:40 编辑 ] === View 层代码 === 用户列表界面`userList.pih:`{{{ project digyn <% Include("/digyn/web/banner.frag") Include("/digyn/web/side.frag.pih") %>
<% pager = userPager %> <%for user in userPager.nowList: %> <%end%>
用户名字现参与项目删除授权为管理员
<%=user.name.encode('utf-8')%> <% for p in user.joinProjects :%> <%=p.name.encode('utf-8')%>  <% end %> <% if user.manageProjects.count() >1 :%> 项目负责中 <% end %> <% else :%> <%=user.id%>')">删除该用户 <% end %> <%=user.id%>" <% if user.id == Session().userId: print "disabled" %> <% else: print "onclick='changeState(this)'" %> <% if (user.is_admin):%> checked <% end %> >
<% print "

共有记录 %s条,分为%s页,每页%s条记录 ,当前第%s页
" % (pager.totleElementNumber,pager.totlePageNum,pager.pageSize,pager.currentPN) %> <% if pager.havePrev():%> <% print "上一页" % (pager.currentPN-1) %> <%end%> <% if pager.haveNext():%> <% print "下一页" % (pager.currentPN+1) %> <%end%>

}}} 分页器:`pager.py:` {{{#!python import math class Pager(object): def __init__(self,nowList,currentPN,pageSize,totleElementNumber): self.nowList = nowList self.currentPN = currentPN self.pageSize = pageSize self.totleElementNumber = totleElementNumber def getTotlePageNum(self): return int(math.ceil(self.totleElementNumber / float(self.pageSize))) totlePageNum = property(fget=getTotlePageNum,doc="return totle page number") def havePrev(self): if self.currentPN >1: return True else: return False def haveNext(self): if ((self.currentPN*self.pageSize)http://zoomquiet.org 博 @ http://blog.zoomquiet.org/pyblosxom/ 维 @ http://wiki.woodpecker.org.cn/moin/ZoomQuiet 豆 @ http://www.douban.com/people/zoomq/ 看 @ http://zoomq.haokanbu.com/ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Pls. usage OOo to replace M$ Office. http://zh.openoffice.org Pls. usage 7-zip to replace WinRAR/WinZip. http://7-zip.org You can get the truely Freedom 4 software.

[导入自Mailman归档:http://www.zeuux.org/pipermail/zeuux-python]

2007年12月17日 星期一 09:01

疯了的决 itanyx在gmail.com
星期一 十二月 17 09:01:04 HKT 2007

也是哈 我就想呢 既然变量都不用声明了 为什么不做到模块也不用引用呢?
自己构建个编译器世界 在世界里加个索引 用到什么自动加载什么 岂不是更方便...

Zoom.Quiet 写道:
> 感谢 lv yi <lvscar在gmail.com> 的分享!
> http://wiki.woodpecker.org.cn/moin/KarrigellStorm
>
> = 装在推车里的暴风雪 =
>  * 原始文章:http://bbs.chinaunix.net/thread-1030014-1-1.html ^2007-12-16 23:02 ^
>
> 活在这个到处web n.0 的时代,无论工作还是爱好,出个web小项目,这需求对咱程序员实在是太普遍了。
> 作为python爱好者,你会杂办?
> 把django资料找出来花个3个月,熟悉它庞大的结构。独特的ORM,和各种taglib ?
> 哈,俺们又不是可怜的ruby用户。
> 你完全可以在python世界里信手拈起最适合你的组件,以最快的速度构建起你自己的web框架。
>
> 如果你的项目符合以下条件,你或许可以考虑 karrigell + storm
>
>
>     * 不需要承载海量用户并发访问
>     * 快速上手的开发过程
>     * 需要高可读性和易于维护的代码
>     * 延续你在java中习惯的mvc思想
>     * 使用人性化的ORM进行db操作
>     * 简单的部署步骤
>
>
> == 先是一点背景: ==
>
> === Karrigell: ===
>
> Karrigell  是轻量级的web框架。灵活,直观,数据库/ORM/模板引擎 独立。
>
> Karrigell 很容易上手,花个1小时把tutorial一看,就能用html和python代码拼出个简单的web程序出来。
>
> Karrigell 支持多种方式混合python代码和html。无论你以前有哪一派的背静,都能在karrigell里延续你的经验和习惯。
>
> Karrigell 部署简单。有python运行环境,就能让它跑的欢畅。
>
> Karrigell代码成熟。 5年来Karrigell基本保持着半年一个版本速度在成长。
>
>
> === Storm   ===
>
> Storm 是由Canonical开发的一套 Python ORM库,用在支持着ubunut的Launchpad项目上。
>
> 以下是Storm的一些亮点(翻译自storm官方网站):
>
> 干净的轻量级API使得Storm的学习上手过程相对轻松。基于Storm的代码也有着友好的维护性.
>
> Storm由测试驱动模式开发,任何一行没经过测试的代码都被认为存在bug。
>
> Storm 中的Model类 不需要特别的构造器,也不需要强制使用专门的基类。
>
> Storm 整体设计得很好。 (代码中不同的部分有着非常清晰的边界。公共api数量小和意义明确)
>
> Storm从一开始以同时支持轻量级(SQLite)和重量级(PostgreSQL / MYSQL)而设计。
>
> Storm代码遵循KISS原则编写,代码简单易读,调试方便。
>
> Storm从一开始就为着同时支持低端小程序和高端(多个数据库,十亿级数据量)而设计。
>
> === 相关学习资料 ===
> karrigell和storm 都很pythonic,看完toturial 基本就能上手.
> 想深入了解就直接看代码。代码均干净整洁,注释详尽。看这类项目的码是享受啊:
>
>  * karrigell的toturial地址:http://karrigell.sourceforge.net/en/front.htm
>  * ChumpKlutz 朽木兄对这这份toturial进行了翻,可以到他的blog 查看:http://blog.csdn.net/chumpklutz/
>
>  * storm的toturial地址:https://storm.canonical.com/Tutorial
>   * 目前还没有中文版,俺争取下月完成这份toturial的翻译.
>
>
> == 对Karrigell的MVC化规范 ==
> karrigell 附带的demo是学习karrigell最好的途径。Karrigell的各种用法都在这七八个demo中有精彩的体现。但或许是作者刻意想通过这几个
> demo 体现出karrigell的灵活,phi,hip,ks 混合起来蛮容易把人搞晕。而且附带的几个demo
> 代码组织都很松散,往往就是把一堆phi,hip,ks,js,gif放在一起了事。如果之前看过rails或django
> 可能会不太适应karrigell demo中的这种凌乱感。
>
> 哈,别慌,如果愿意,你完全可以把你的项目按照天条似的mvc结构来组织。加上少许规范,karrigell也能秀出rails那样的形式主义美。
>
> 下面是,我的一个小项目的
> === 代码安排: ===
> 在 karrigell webapps 目录下,用你喜欢的名字命名你的karrigell工程。
> 工程目录下,新建:{{{
> conf/  control/   model/  service/  test/  util/  web/  这几个目录,
> 以及 index.pih   和 __init__.py
> }}}
> 我的习惯是把`目录恒量`,和数据库配置放在 conf 下。
>  * ORM 对象 放在 model 目录;
>  * service目录下放置业务代码;
>  * util里放入第三方库;
>  * test里写点小测试代码。
>  * 所有前台代码,都放到web目录里,所以web目录下可以再新建几个js/ css/ uploadFiles/  这样的目录。
>   * web目录下,只写和前台展现相关的代码,根据页面的复杂程度,在pih和hip中选择。
>  * contorl目录下,只写页面跳转,为web目录下的pih和hip提供变量 和调用相关业务方法的代码。 ks是最好的选择。
> 同一个对象,不同的web行为。可以写在成一个ks中的多个方法。
>
>  tips:: ks 中不能直接捕获引入方法抛出的异常,因为异常在 core.k_script  里已经被捕获并做了处理。
> 我的解决方法是,把所有自己用到的异常的自定义父类 添加到
> core/k_script.py 154行左右  直接抛出捕获异常的 except 字句参数里。
> 然后再把所有用到的异常引入 modules/mod_ks.py 中。
>
>
> === 集成Storm: ===
> karrigell 集成storm可以说是非常方便。 把storm 解压后,放到 karrigell的 /databases 目录。
> 在我们的项目的 conf/ 目录下 建立个storm_conf.py 的module 内容如下:
> {{{#!python
> fromdatabases.storm.locals import *
> db_url = "postgres://lvs:car@localhost/digyn_dev"
>
> database = None
> store = None
> def getStore():
>     global store
>     if store == None:
>         store = Store(getDatabase())
>
>     return store
>
>
> def getDatabase():
>     global database
>     if database == None:
>         database = create_database(db_url)
>     return database
>
> #因为采用了module 全局变量。引用此module在最好统一为绝对包名引用
> }}}
>
> 然后,我们就可以在service里 像这样自然的进行数据的持久化操作:
> {{{#!python
> from webapps.digyn.model.orm_models import *
> from webapps.digyn.util.pager import Pager
> from webapps.digyn.conf import storm_conf
> store = storm_conf.getStore()
> def add(moduleId,title,bugInfo,findDate,findUserId):
>     bug = Bug(moduleId,title,findDate,findUserId,bugInfo)
>     bug.bug_state = constantValue.bugState_new
>     store.add(bug)
>     store.commit()
>     return bug.id
>
> def get(bugId):
>     return store.get(Bug,bugId)
>
> def getBugsPagerForModule(moduleId,bugState,pageNumber=1,pageSize=10):
>     """获取特定模块下特定状态的bug"""
>     resList = store.find(Bug,Bug.module_id == moduleId,Bug.bug_state
> == bugState).order_by(Bug.id)
>     presList = resList[(pageNumber-1)*pageSize:pageNumber*pageSize]
>     return Pager(presList,pageNumber,pageSize,resList.count())
>
> }}}
> [ 本帖最后由 lvscar 于 2007-12-17 01:12 编辑 ]
>
> === 后台到前台的代码片段 ===
>
> 从后台到前台实现用户管理功能的代码片段:
>
> storm ORM 对象  `orm_models.py:`
> {{{!python
> import md5
> from databases.storm.locals import *
>
> class User(Storm):
>     __storm_table__='users'
>     id = Int(primary=True)
>     password =  RawStr()
>     name = Unicode()
>     info = Unicode()
>     is_admin = Bool()
>     manageProjects = ReferenceSet('User.id','Project.manager_id')
>     joinProjects =
> ReferenceSet(id,'_UserProjectRelation.user_id','_UserProjectRelation.project_id','Project.id')
>     joinModules =
> ReferenceSet(id,'_UserModuleRelation.user_id','_UserModuleRelation.module_id','Module.id')
>
>     def __init__(self,name,password,is_admin=False):
>         self.name = name
>         self.password = password
>         self.is_admin = is_admin
>
>     def __setattr__(self,name,value):
>         if name == 'password':
>             #self.__dict__['password'] = value   #设值是通过Storm
> 属性类的__set__方法(重载 '='操作符 )实现的。改变instance中的值,变化不会被storm察觉
>             processedPassword = md5.new(value).digest()
>             User.password.__set__(self,processedPassword)
>         else:
>             super(User,self).__setattr__(name,value)
> }}}
>
> 虽说 Storm orm对象不需要继承特别的父类,但继承Storm类会带来一个方便,
> 在建立对象关系时,可以用字符串引用其他类。
>
> Service层代码:`userService.py:`
> {{{#!python
> import md5
> from webapps.digyn.conf import storm_conf
> from common.exception import *
> from webapps.digyn.model.orm_models import User
> from webapps.digyn.util.pager import Pager
>
> store = storm_conf.getStore()
>
> def addUser(name,password):
>     if checkUserNameUsed(name):
>         raise NameDuplicate, name
>     user = User(name,password)
>     store.add(user)
>     store.commit()
>
> def checkUserNameUsed(name):
>     if store.find(User,User.name == name).one():
>         return True
>     else:
>         return False
>
> def deleteUser(userId):
>     user = get(userId)
>     store.remove(user)
>     store.commit()
>
> def loginValidate(name,password):
>     password = md5.new(password).digest()
>     user = store.find(User,User.name == name,User.password == password).one()
>     if user:
>         return user
>     else:
>         return False
> def get(userId):
>     return store.get(User,int(userId))
>
> def getAllUser():
>     return store.find(User)
>
> def getManageProjects(userId):
>
>     user = store.get(User,int(userId))
>     projectList = []
>     for p in user.manageProjects:
>         projectList.append(p)
>     return projectList
>
> def getjoinProjects(userId):
>     user = store.get(User,int(userId))
>     projectList = []
>     for p in user.joinProjects:
>         projectList.append(p)
>     return projectList
> def assignAdmin(act,userId):
>     user = get(userId)
>     if act == 'add':
>         user.is_admin = True
>     elif act == 'remove':
>         user.is_admin = False
>     store.commit()
>
> def getUserPager(pageNumber =1,nameQueryStr = None,pageSize=10):
>         if (nameQueryStr and len(nameQueryStr) > 0):
>             resList = store.find(User,User.name.like(u"%"+nameQueryStr+u"%"))
>         else:
>             resList = store.find(User)
>         resList = resList[(pageNumber-1)*pageSize:pageNumber*pageSize]
>         return Pager(resList,pageNumber,pageSize,resList.count())
> }}}
>
> 顶楼那个tips的意义,就在于可以让Service层中写addUser方法时,我们可以直接抛出一个自定意异常,让control层代码可以写成下面这种格式:{{{
>      try:
>         userService.addUser(name,password)
>     except NameDuplicate,userName:
>         Include("/digyn/web/user/register.pih",flash="用户 %s 已经存在"
> %str(userName))
>         return
>     Include("/digyn/index.pih",flash="%s 你的帐号已添加,请登录"  % (name.encode('utf-8')))
> }}}
> [ 本帖最后由 lvscar 于 2007-12-17 00:25 编辑 ]
>
>
> === Control层代码 ===
>  * `userControl.ks`:
> {{{#!python
> #-*- coding:utf-8 -*-
> from webapps.digyn.service import userService
> from common.exception import *
> PageSize = 10
>
> def register(name,password,password_again):
>     name = unicode(name,'utf-8')
>     if(password != password_again):
>         Include("/digyn/web/user/register.pih",flash="两次输入的密码不符")
>         return
>     try:
>         userService.addUser(name,password)
>     except NameDuplicate,userName:
>         Include("/digyn/web/user/register.pih",flash="用户 %s 已经存在"
> %str(userName))
>         return
>     Include("/digyn/index.pih",flash="%s 你的帐号已添加,请登录"  % (name.encode('utf-8')))
>
> def login(name,password):
>     name = unicode(name,'utf-8')
>     user = userService.loginValidate(name,password)
>     if user:
>         session = Session()
>         session.userId = user.id
>         if user.is_admin:
>             session.is_admin = True
>         else:
>             session.is_admin = False
>         Include("/digyn/web/user/userIndex.pih",user=user)
>         return
>     else:
>         Include("/digyn/web/user/login.pih" ,flash="该用户不存在或密码错误")
>
> def logout():
>     Session().close()
>     raise HTTP_REDIRECTION,"/digyn"
>
> def userManage(act,pageNumber=1):
>     pageNumber  = int(pageNumber)
>     _checkIsAdmin()
>
>     if act == "list":
>         _getUserPager(pageNumber)
>
> def _getUserPager(pageNumber ,nameQueryStr = None,pageSize=PageSize):
>     userPager = userService.getUserPager(int(pageNumber),pageSize=pageSize)
>     Include("/digyn/web/admin/userList.pih",userPager=userPager)
>
> def assignAdmin(act,userId):
>     """设定用户是否为系统管理员"""
>     _checkIsAdmin()
>     userId = int(userId)
>     if act == "add":
>         userService.assignAdmin("add",userId)
>     elif act == "remove":
>         userService.assignAdmin("remove",userId)
>     else:
>         print "erroe"
>         return
>     print "success"
>
> def deleteUser(userId):
>     _checkIsAdmin()
>     userId = int(userId)
>     userName = userService.get(userId).name
>     userService.deleteUser(userId)
>     userPager = userService.getUserPager(1,pageSize=pageSize)
>     Include("/digyn/web/admin/userList.pih",userPager=userPager,flash="用户
> %s 已经删除" %(userName.encode('utf-8')))
>
> def _checkUserLogin():
>     if not hasattr(Session(),'userId'):
>         Session().close()
>         Include("/digyn/web/user/login.pih",flash="请先登录")
>         raise SCRIPT_END
> def _checkIsAdmin():
>     if(( not hasattr(Session(),'is_admin')) or (not Session().is_admin)):
>         Session().close()
>         Include("/digyn/index.pih",flash="你未被授权访问")
>         raise SCRIPT_END
> }}}
>
> Control层一个方法对应 一个web动作,表单参数名直接用做方法参数。 通过url来决定调用哪个方法
> 例如下面的表单实现用户登录:
> {{{
> 
> 用户名
> 密码
> >
> }}} > Include 和 raise HTTP_REDIRECTION 这两种实现url转向的方法类似 java servlet编程中的 > sendRedirect 和 forward > > 通过_checkUserLogin /_checkIsAdmin 提高安全性,实现 rails中的 before filter 的效果。 > > [ 本帖最后由 lvscar 于 2007-12-17 00:40 编辑 ] > > === View 层代码 === > > 用户列表界面`userList.pih:`{{{ > > > project digyn > > > type="text/css" /> > > > > > > <% > Include("/digyn/web/banner.frag") > Include("/digyn/web/side.frag.pih") > %> >
> > <% > pager = userPager > > %> >
> > 用户名字现参与项目删除授权为管理员 > > <%for user in userPager.nowList: %> > > <%=user.name.encode('utf-8')%> > > > > <% for p in user.joinProjects :%> > <%=p.name.encode('utf-8')%>  > <% end %> > > > > > <% if user.manageProjects.count() >1 :%> > 项目负责中 > <% end %> > <% else :%> > > onclick="openUrlWithConfirm('/digyn/control/userControl.ks/deleteUser?userId=<%=user.id%>')">删除该用户 > <% end %> > > > > value="<%=user.id%>" > <% if user.id == Session().userId: > print "disabled" > %> > <% else: > print "onclick='changeState(this)'" > %> > <% if (user.is_admin):%> > checked > <% end %> > > > > > <%end%> > > <% > print "

共有记录 %s条,分为%s页,每页%s条记录 ,当前第%s页
" % > (pager.totleElementNumber,pager.totlePageNum,pager.pageSize,pager.currentPN) > %> > <% if pager.havePrev():%> > <% print "> href='/digyn/control/userControl.ks/userManage?act=list&pageNumber;=%s'>上一页" > % (pager.currentPN-1) %> > <%end%> > <% if pager.haveNext():%> > <% print "> href='/digyn/control/userControl.ks/userManage?act=list&pageNumber;=%s'>下一页" > % (pager.currentPN+1) %> > <%end%> > > > > > > }}} > > > 分页器:`pager.py:` > {{{#!python > import math > class Pager(object): > def __init__(self,nowList,currentPN,pageSize,totleElementNumber): > self.nowList = nowList > self.currentPN = currentPN > self.pageSize = pageSize > self.totleElementNumber = totleElementNumber > > def getTotlePageNum(self): > return int(math.ceil(self.totleElementNumber / float(self.pageSize))) > totlePageNum = property(fget=getTotlePageNum,doc="return totle page number") > def havePrev(self): > if self.currentPN >1: > return True > else: > return False > def haveNext(self): > if ((self.currentPN*self.pageSize)> return True > else: > return False > }}} > > [ 本帖最后由 lvscar 于 2007-12-17 00:46 编辑 ] > > = 反馈 = > [[PageComment2]] > > >


[导入自Mailman归档:http://www.zeuux.org/pipermail/zeuux-python]

2007年12月17日 星期一 09:03

朽木klutz chumpklutz在gmail.com
星期一 十二月 17 09:03:15 HKT 2007

ŒWÁ•Ö®

ÔÚ07-12-17£¬Zoom. Quiet <zoom.quiet在gmail.com> дµÀ£º
>
> ¸Ðл lv yi <lvscar在gmail.com> µÄ·ÖÏí£¡
> http://wiki.woodpecker.org.cn/moin/KarrigellStorm
>
> = ×°ÔÚÍÆ³µÀïµÄ±©·çÑ© =
> * ԭʼÎÄÕÂ:http://bbs.chinaunix.net/thread-1030014-1-1.html ^2007-12-16 23:02
> ^
>
> »îÔÚÕâ¸öµ½´¦web n.0 µÄʱ´ú£¬ÎÞÂÛ¹¤×÷»¹Êǰ®ºÃ£¬³ö¸öwebСÏîÄ¿£¬ÕâÐèÇó¶ÔÔÛ³ÌÐòԱʵÔÚÊÇÌ«ÆÕ±éÁË¡£
> ×÷Ϊpython°®ºÃÕߣ¬Äã»áÔӰ죿
> °Ñdjango×ÊÁÏÕÒ³öÀ´»¨¸ö3¸öÔ£¬ÊìϤËüÅÓ´óµÄ½á¹¹¡£¶ÀÌØµÄORM£¬ºÍ¸÷ÖÖtaglib £¿
> ¹þ£¬°³ÃÇÓÖ²»ÊÇ¿ÉÁ¯µÄrubyÓû§¡£
> ÄãÍêÈ«¿ÉÒÔÔÚpythonÊÀ½çÀïÐÅÊÖÄéÆð×îÊʺÏÄãµÄ×é¼þ£¬ÒÔ×î¿ìµÄËٶȹ¹½¨ÆðÄã×Ô¼ºµÄweb¿ò¼Ü¡£
>
> Èç¹ûÄãµÄÏîÄ¿·ûºÏÒÔÏÂÌõ¼þ£¬Äã»òÐí¿ÉÒÔ¿¼ÂÇ karrigell + storm
>
>
>    * ²»ÐèÒª³ÐÔØº£Á¿Óû§²¢·¢·ÃÎÊ
>    * ¿ìËÙÉÏÊֵĿª·¢¹ý³Ì
>    * ÐèÒª¸ß¿É¶ÁÐÔºÍÒ×ÓÚά»¤µÄ´úÂë
>    * ÑÓÐøÄãÔÚjavaÖÐϰ¹ßµÄmvc˼Ïë
>    * ʹÓÃÈËÐÔ»¯µÄORM½øÐÐdb²Ù×÷
>    * ¼òµ¥µÄ²¿Êð²½Öè
>
>
> == ÏÈÊÇÒ»µã±³¾°: ==
>
> === Karrigell£º ===
>
> Karrigell  ÊÇÇáÁ¿¼¶µÄweb¿ò¼Ü¡£Áé»î£¬Ö±¹Û£¬Êý¾Ý¿â£¯ORM£¯Ä£°åÒýÇæ ¶ÀÁ¢¡£
>
> Karrigell ºÜÈÝÒ×ÉÏÊÖ£¬»¨¸ö1Сʱ°ÑtutorialÒ»¿´£¬¾ÍÄÜÓÃhtmlºÍpython´úÂëÆ´³ö¸ö¼òµ¥µÄweb³ÌÐò³öÀ´¡£
>
> Karrigell Ö§³Ö¶àÖÖ·½Ê½»ìºÏpython´úÂëºÍhtml¡£ÎÞÂÛÄãÒÔǰÓÐÄÄÒ»Åɵı³¾²£¬¶¼ÄÜÔÚkarrigellÀïÑÓÐøÄãµÄ¾­ÑéºÍϰ¹ß¡£
>
> Karrigell ²¿Êð¼òµ¥¡£ÓÐpythonÔËÐл·¾³£¬¾ÍÄÜÈÃËüÅܵ϶³©¡£
>
> Karrigell´úÂë³ÉÊì¡£ 5ÄêÀ´Karrigell»ù±¾±£³Ö×ŰëÄêÒ»¸ö°æ±¾ËÙ¶ÈÔڳɳ¤¡£
>
>
> === Storm   ===
>
> Storm ÊÇÓÉCanonical¿ª·¢µÄÒ»Ì× Python ORM¿â£¬ÓÃÔÚÖ§³Ö×ÅubunutµÄLaunchpadÏîÄ¿ÉÏ¡£
>
> ÒÔÏÂÊÇStormµÄһЩÁÁµã£¨·­Òë×Ôstorm¹Ù·½ÍøÕ¾£©£º
>
> ¸É¾»µÄÇáÁ¿¼¶APIʹµÃStormµÄѧϰÉÏÊÖ¹ý³ÌÏà¶ÔÇáËÉ¡£»ùÓÚStormµÄ´úÂëÒ²ÓÐ×ÅÓѺõÄά»¤ÐÔ.
>
> StormÓɲâÊÔÇý¶¯Ä£Ê½¿ª·¢,ÈκÎÒ»ÐÐû¾­¹ý²âÊԵĴúÂë¶¼±»ÈÏΪ´æÔÚbug¡£
>
> Storm ÖеÄModelÀà ²»ÐèÒªÌØ±ðµÄ¹¹ÔìÆ÷£¬Ò²²»ÐèÒªÇ¿ÖÆÊ¹ÓÃרÃŵĻùÀà¡£
>
> Storm ÕûÌåÉè¼ÆµÃºÜºÃ¡£ £¨´úÂëÖв»Í¬µÄ²¿·ÖÓÐ×ŷdz£ÇåÎúµÄ±ß½ç¡£¹«¹²apiÊýÁ¿Ð¡ºÍÒâÒåÃ÷È·£©
>
> Storm´ÓÒ»¿ªÊ¼ÒÔͬʱ֧³ÖÇáÁ¿¼¶£¨SQLite£©ºÍÖØÁ¿¼¶£¨PostgreSQL £¯ MYSQL£©¶øÉè¼Æ¡£
>
> Storm´úÂë×ñÑ­KISSÔ­Ôò±àд£¬´úÂë¼òµ¥Ò×¶Á£¬µ÷ÊÔ·½±ã¡£
>
> Storm´ÓÒ»¿ªÊ¼¾ÍΪ×Åͬʱ֧³ÖµÍ¶ËС³ÌÐòºÍ¸ß¶Ë£¨¶à¸öÊý¾Ý¿â£¬Ê®ÒÚ¼¶Êý¾ÝÁ¿£©¶øÉè¼Æ¡£
>
> === Ïà¹ØÑ§Ï°×ÊÁÏ ===
> karrigellºÍstorm ¶¼ºÜpythonic£¬¿´Íêtoturial »ù±¾¾ÍÄÜÉÏÊÖ.
> ÏëÉîÈëÁ˽â¾ÍÖ±½Ó¿´´úÂë¡£´úÂë¾ù¸É¾»Õû½à£¬×¢ÊÍÏ꾡¡£¿´ÕâÀàÏîÄ¿µÄÂëÊÇÏíÊܰ¡£º
>
> * karrigellµÄtoturialµØÖ·£ºhttp://karrigell.sourceforge.net/en/front.htm
> * ChumpKlutz ÐàľÐÖ¶ÔÕâÕâ·Ýtoturial½øÐÐÁË·­£¬¿ÉÒÔµ½ËûµÄblog ²é¿´£º
> http://blog.csdn.net/chumpklutz/
>
> * stormµÄtoturialµØÖ·£ºhttps://storm.canonical.com/Tutorial
> * Ŀǰ»¹Ã»ÓÐÖÐÎİ棬°³ÕùÈ¡ÏÂÔÂÍê³ÉÕâ·ÝtoturialµÄ·­Òë.
>
>
> == ¶ÔKarrigellµÄMVC»¯¹æ·¶ ==
> karrigell
> ¸½´øµÄdemoÊÇѧϰkarrigell×îºÃµÄ;¾¶¡£KarrigellµÄ¸÷ÖÖÓ÷¨¶¼ÔÚÕâÆß°Ë¸ödemoÖÐÓо«²ÊµÄÌåÏÖ¡£µ«»òÐíÊÇ×÷Õß¿ÌÒâÏëͨ¹ýÕ⼸¸ö
> demo ÌåÏÖ³ökarrigellµÄÁé»î£¬phi£¬hip£¬ks »ìºÏÆðÀ´ÂùÈÝÒ×°ÑÈ˸ãÔΡ£¶øÇÒ¸½´øµÄ¼¸¸ödemo
> ´úÂë×éÖ¯¶¼ºÜËÉÉ¢£¬ÍùÍù¾ÍÊǰÑÒ»¶Ñphi,hip,ks,js,gif·ÅÔÚÒ»ÆðÁËÊ¡£Èç¹û֮ǰ¿´¹ýrails»òdjango
> ¿ÉÄܻ᲻̫ÊÊÓ¦karrigell demoÖеÄÕâÖÖÁèÂҸС£
>
> ¹þ£¬±ð»Å£¬Èç¹ûÔ¸Ò⣬ÄãÍêÈ«¿ÉÒÔ°ÑÄãµÄÏîÄ¿°´ÕÕÌìÌõËÆµÄmvc½á¹¹À´×éÖ¯¡£¼ÓÉÏÉÙÐí¹æ·¶£¬karrigellÒ²ÄÜÐã³örailsÄÇÑùµÄÐÎʽÖ÷ÒåÃÀ¡£
>
> ÏÂÃæÊÇ£¬ÎÒµÄÒ»¸öСÏîÄ¿µÄ
> === ´úÂë°²ÅÅ£º ===
> ÔÚ karrigell webapps Ŀ¼Ï£¬ÓÃÄãϲ»¶µÄÃû×ÖÃüÃûÄãµÄkarrigell¹¤³Ì¡£
> ¹¤³ÌĿ¼Ï£¬Ð½¨£º{{{
> conf/  control/   model/  service/  test/  util/  web/  Õ⼸¸öĿ¼£¬
> ÒÔ¼° index.pih   ºÍ __init__.py
> }}}
> ÎÒµÄϰ¹ßÊǰÑ`Ŀ¼ºãÁ¿`£¬ºÍÊý¾Ý¿âÅäÖ÷ÅÔÚ conf Ï¡£
> * ORM ¶ÔÏó ·ÅÔÚ model Ŀ¼£»
> * serviceĿ¼Ï·ÅÖÃÒµÎñ´úÂ룻
> * utilÀï·ÅÈëµÚÈý·½¿â£»
> * testÀïдµãС²âÊÔ´úÂë¡£
> * ËùÓÐǰ̨´úÂ룬¶¼·Åµ½webĿ¼ÀËùÒÔwebĿ¼Ï¿ÉÒÔÔÙн¨¼¸¸öjs/ css/ uploadFiles/  ÕâÑùµÄĿ¼¡£
> * webĿ¼Ï£¬Ö»Ð´ºÍǰ̨չÏÖÏà¹ØµÄ´úÂ룬¸ù¾ÝÒ³ÃæµÄ¸´Ôӳ̶ȣ¬ÔÚpihºÍhipÖÐÑ¡Ôñ¡£
> * contorlĿ¼Ï£¬Ö»Ð´Ò³ÃæÌø×ª£¬ÎªwebĿ¼ÏµÄpihºÍhipÌṩ±äÁ¿ ºÍµ÷ÓÃÏà¹ØÒµÎñ·½·¨µÄ´úÂë¡£ ksÊÇ×îºÃµÄÑ¡Ôñ¡£
> ͬһ¸ö¶ÔÏ󣬲»Í¬µÄwebÐÐΪ¡£¿ÉÒÔдÔÚ³ÉÒ»¸öksÖеĶà¸ö·½·¨¡£
>
> tips:: ks Öв»ÄÜÖ±½Ó²¶»ñÒýÈë·½·¨Å׳öµÄÒì³££¬ÒòΪÒì³£ÔÚ core.k_script  ÀïÒѾ­±»²¶»ñ²¢×öÁË´¦Àí¡£
> ÎҵĽâ¾ö·½·¨ÊÇ£¬°ÑËùÓÐ×Ô¼ºÓõ½µÄÒì³£µÄ×Ô¶¨Ò常Àà Ìí¼Óµ½
> core/k_script.py 154ÐÐ×óÓÒ  Ö±½ÓÅ׳ö²¶»ñÒì³£µÄ except ×Ö¾ä²ÎÊýÀï¡£
> È»ºóÔÙ°ÑËùÓÐÓõ½µÄÒì³£ÒýÈë modules/mod_ks.py ÖС£
>
>
> === ¼¯³ÉStorm£º ===
> karrigell ¼¯³Éstorm¿ÉÒÔ˵ÊǷdz£·½±ã¡£ °Ñstorm ½âѹºó£¬·Åµ½ karrigellµÄ /databases Ŀ¼¡£
> ÔÚÎÒÃǵÄÏîÄ¿µÄ conf/ Ŀ¼Ï ½¨Á¢¸östorm_conf.py µÄmodule ÄÚÈÝÈçÏÂ:
> {{{#!python
> fromdatabases.storm.locals import *
> db_url = "postgres://lvs:car@localhost/digyn_dev"
>
> database = None
> store = None
> def getStore():
>    global store
>    if store == None:
>        store = Store(getDatabase())
>
>    return store
>
>
> def getDatabase():
>    global database
>    if database == None:
>        database = create_database(db_url)
>    return database
>
> #ÒòΪ²ÉÓÃÁËmodule È«¾Ö±äÁ¿¡£ÒýÓôËmoduleÔÚ×îºÃͳһΪ¾ø¶Ô°üÃûÒýÓÃ
> }}}
>
> È»ºó£¬ÎÒÃǾͿÉÒÔÔÚserviceÀï ÏñÕâÑù×ÔÈ»µÄ½øÐÐÊý¾ÝµÄ³Ö¾Ã»¯²Ù×÷£º
> {{{#!python
> from webapps.digyn.model.orm_models import *
> from webapps.digyn.util.pager import Pager
> from webapps.digyn.conf import storm_conf
> store = storm_conf.getStore()
> def add(moduleId,title,bugInfo,findDate,findUserId):
>    bug = Bug(moduleId,title,findDate,findUserId,bugInfo)
>    bug.bug_state = constantValue.bugState_new
>    store.add(bug)
>    store.commit()
>    return bug.id
>
> def get(bugId):
>    return store.get(Bug,bugId)
>
> def getBugsPagerForModule(moduleId,bugState,pageNumber=1,pageSize=10):
>    """»ñÈ¡ÌØ¶¨Ä£¿éÏÂÌØ¶¨×´Ì¬µÄbug"""
>    resList = store.find(Bug,Bug.module_id == moduleId,Bug.bug_state
> == bugState).order_by(Bug.id)
>    presList = resList[(pageNumber-1)*pageSize:pageNumber*pageSize]
>    return Pager(presList,pageNumber,pageSize,resList.count())
>
> }}}
> [ ±¾Ìû×îºóÓÉ lvscar ÓÚ 2007-12-17 01:12 ±à¼­ ]
>
> === ºǫ́µ½Ç°Ì¨µÄ´úÂëÆ¬¶Î ===
>
> ´Óºǫ́µ½Ç°Ì¨ÊµÏÖÓû§¹ÜÀí¹¦ÄܵĴúÂëÆ¬¶Î£º
>
> storm ORM ¶ÔÏó  `orm_models.py:`
> {{{!python
> import md5
> from databases.storm.locals import *
>
> class User(Storm):
>    __storm_table__='users'
>    id = Int(primary=True)
>    password =  RawStr()
>    name = Unicode()
>    info = Unicode()
>    is_admin = Bool()
>    manageProjects = ReferenceSet('User.id','Project.manager_id')
>    joinProjects =
>
> ReferenceSet(id,'_UserProjectRelation.user_id','_UserProjectRelation.project_id','
> Project.id')
>    joinModules =
>
> ReferenceSet(id,'_UserModuleRelation.user_id','_UserModuleRelation.module_id','
> Module.id')
>
>    def __init__(self,name,password,is_admin=False):
>        self.name = name
>        self.password = password
>        self.is_admin = is_admin
>
>    def __setattr__(self,name,value):
>        if name == 'password':
>            #self.__dict__['password'] = value   #ÉèÖµÊÇͨ¹ýStorm
> ÊôÐÔÀàµÄ__set__·½·¨£¨ÖØÔØ '='²Ù×÷·û )ʵÏֵġ£¸Ä±äinstanceÖеÄÖµ£¬±ä»¯²»»á±»storm²ì¾õ
>            processedPassword = md5.new(value).digest()
>            User.password.__set__(self,processedPassword)
>        else:
>            super(User,self).__setattr__(name,value)
> }}}
>
> Ëä˵ Storm orm¶ÔÏó²»ÐèÒª¼Ì³ÐÌØ±ðµÄ¸¸À࣬µ«¼Ì³ÐStormÀà»á´øÀ´Ò»¸ö·½±ã£¬
> ÔÚ½¨Á¢¶ÔÏó¹ØÏµÊ±£¬¿ÉÒÔÓÃ×Ö·û´®ÒýÓÃÆäËûÀà¡£
>
> Service²ã´úÂ룺`userService.py:`
> {{{#!python
> import md5
> from webapps.digyn.conf import storm_conf
> from common.exception import *
> from webapps.digyn.model.orm_models import User
> from webapps.digyn.util.pager import Pager
>
> store = storm_conf.getStore()
>
> def addUser(name,password):
>    if checkUserNameUsed(name):
>        raise NameDuplicate, name
>    user = User(name,password)
>    store.add(user)
>    store.commit()
>
> def checkUserNameUsed(name):
>    if store.find(User,User.name == name).one():
>        return True
>    else:
>        return False
>
> def deleteUser(userId):
>    user = get(userId)
>    store.remove(user)
>    store.commit()
>
> def loginValidate(name,password):
>    password = md5.new(password).digest()
>    user = store.find(User,User.name == name,User.password ==
> password).one()
>    if user:
>        return user
>    else:
>        return False
> def get(userId):
>    return store.get(User,int(userId))
>
> def getAllUser():
>    return store.find(User)
>
> def getManageProjects(userId):
>
>    user = store.get(User,int(userId))
>    projectList = []
>    for p in user.manageProjects:
>        projectList.append(p)
>    return projectList
>
> def getjoinProjects(userId):
>    user = store.get(User,int(userId))
>    projectList = []
>    for p in user.joinProjects:
>        projectList.append(p)
>    return projectList
> def assignAdmin(act,userId):
>    user = get(userId)
>    if act == 'add':
>        user.is_admin = True
>    elif act == 'remove':
>        user.is_admin = False
>    store.commit()
>
> def getUserPager(pageNumber =1,nameQueryStr = None,pageSize=10):
>        if (nameQueryStr and len(nameQueryStr) > 0):
>            resList = store.find(User,User.name.like
> (u"%"+nameQueryStr+u"%"))
>        else:
>            resList = store.find(User)
>        resList = resList[(pageNumber-1)*pageSize:pageNumber*pageSize]
>        return Pager(resList,pageNumber,pageSize,resList.count())
> }}}
>
>
> ¶¥Â¥ÄǸötipsµÄÒâÒ壬¾ÍÔÚÓÚ¿ÉÒÔÈÃService²ãÖÐдaddUser·½·¨Ê±£¬ÎÒÃÇ¿ÉÒÔÖ±½ÓÅ׳öÒ»¸ö×Ô¶¨ÒâÒì³££¬ÈÃcontrol²ã´úÂë¿ÉÒÔд³ÉÏÂÃæÕâÖÖ¸ñʽ£º{{{
>     try:
>        userService.addUser(name,password)
>    except NameDuplicate,userName:
>        Include("/digyn/web/user/register.pih",flash="Óû§ %s ÒѾ­´æÔÚ"
> %str(userName))
>        return
>    Include("/digyn/index.pih",flash="%s ÄãµÄÕʺÅÒÑÌí¼Ó£¬ÇëµÇ¼"  % (name.encode
> ('utf-8')))
> }}}
> [ ±¾Ìû×îºóÓÉ lvscar ÓÚ 2007-12-17 00:25 ±à¼­ ]
>
>
> === Control²ã´úÂë ===
> * `userControl.ks`:
> {{{#!python
> #-*- coding:utf-8 -*-
> from webapps.digyn.service import userService
> from common.exception import *
> PageSize = 10
>
> def register(name,password,password_again):
>    name = unicode(name,'utf-8')
>    if(password != password_again):
>        Include("/digyn/web/user/register.pih",flash="Á½´ÎÊäÈëµÄÃÜÂë²»·û")
>        return
>    try:
>        userService.addUser(name,password)
>    except NameDuplicate,userName:
>        Include("/digyn/web/user/register.pih",flash="Óû§ %s ÒѾ­´æÔÚ"
> %str(userName))
>        return
>    Include("/digyn/index.pih",flash="%s ÄãµÄÕʺÅÒÑÌí¼Ó£¬ÇëµÇ¼"  % (name.encode
> ('utf-8')))
>
> def login(name,password):
>    name = unicode(name,'utf-8')
>    user = userService.loginValidate(name,password)
>    if user:
>        session = Session()
>        session.userId = user.id
>        if user.is_admin:
>            session.is_admin = True
>        else:
>            session.is_admin = False
>        Include("/digyn/web/user/userIndex.pih",user=user)
>        return
>    else:
>        Include("/digyn/web/user/login.pih" ,flash="¸ÃÓû§²»´æÔÚ»òÃÜÂë´íÎó")
>
> def logout():
>    Session().close()
>    raise HTTP_REDIRECTION,"/digyn"
>
> def userManage(act,pageNumber=1):
>    pageNumber  = int(pageNumber)
>    _checkIsAdmin()
>
>    if act == "list":
>        _getUserPager(pageNumber)
>
> def _getUserPager(pageNumber ,nameQueryStr = None,pageSize=PageSize):
>    userPager = userService.getUserPager(int(pageNumber),pageSize=pageSize)
>    Include("/digyn/web/admin/userList.pih",userPager=userPager)
>
> def assignAdmin(act,userId):
>    """É趨Óû§ÊÇ·ñΪϵͳ¹ÜÀíÔ±"""
>    _checkIsAdmin()
>    userId = int(userId)
>    if act == "add":
>        userService.assignAdmin("add",userId)
>    elif act == "remove":
>        userService.assignAdmin("remove",userId)
>    else:
>        print "erroe"
>        return
>    print "success"
>
> def deleteUser(userId):
>    _checkIsAdmin()
>    userId = int(userId)
>    userName = userService.get(userId).name
>    userService.deleteUser(userId)
>    userPager = userService.getUserPager(1,pageSize=pageSize)
>    Include("/digyn/web/admin/userList.pih",userPager=userPager,flash="Óû§
> %s ÒѾ­É¾³ý" %(userName.encode('utf-8')))
>
> def _checkUserLogin():
>    if not hasattr(Session(),'userId'):
>        Session().close()
>        Include("/digyn/web/user/login.pih",flash="ÇëÏȵǼ")
>        raise SCRIPT_END
> def _checkIsAdmin():
>    if(( not hasattr(Session(),'is_admin')) or (not Session().is_admin)):
>        Session().close()
>        Include("/digyn/index.pih",flash="Äãδ±»ÊÚȨ·ÃÎÊ")
>        raise SCRIPT_END
> }}}
>
> Control²ãÒ»¸ö·½·¨¶ÔÓ¦ Ò»¸öweb¶¯×÷£¬±íµ¥²ÎÊýÃûÖ±½ÓÓÃ×ö·½·¨²ÎÊý¡£ ͨ¹ýurlÀ´¾ö¶¨µ÷ÓÃÄĸö·½·¨
> ÀýÈçÏÂÃæµÄ±íµ¥ÊµÏÖÓû§µÇ¼£º
> {{{
> 
> Óû§Ãû
> ÃÜÂë
> >
> }}} > Include ºÍ raise HTTP_REDIRECTION ÕâÁ½ÖÖʵÏÖurlתÏòµÄ·½·¨ÀàËÆ java servlet±à³ÌÖÐµÄ > sendRedirect ºÍ forward > > ͨ¹ý_checkUserLogin £¯_checkIsAdmin Ìá¸ß°²È«ÐÔ£¬ÊµÏÖ railsÖÐµÄ before filter µÄЧ¹û¡£ > > [ ±¾Ìû×îºóÓÉ lvscar ÓÚ 2007-12-17 00:40 ±à¼­ ] > > === View ²ã´úÂë === > > Óû§Áбí½çÃæ`userList.pih:`{{{ > > > project digyn > > > type="text/css" /> > > > > > > <% > Include("/digyn/web/banner.frag") > Include("/digyn/web/side.frag.pih") > %> >
> > <% > pager = userPager > > %> >
> > Óû§Ãû×ÖÏÖ²ÎÓëÏîĿɾ³ýÊÚȨΪ¹ÜÀíÔ± > > <%for user in userPager.nowList: %> > > <%=user.name.encode('utf-8')%> > > > > <% for p in user.joinProjects :%> > <%=p.name.encode('utf-8')%>  > <% end %> > > > > > <% if user.manageProjects.count() >1 :%> > ÏîÄ¿¸ºÔðÖÐ > <% end %> > <% else :%> > > > onclick="openUrlWithConfirm('/digyn/control/userControl.ks/deleteUser?userId=<%= > user.id%>')">ɾ³ý¸ÃÓû§ > <% end %> > > > > value="<%=user.id%>" > <% if user.id == Session().userId: > print "disabled" > %> > <% else: > print "onclick='changeState(this)'" > %> > <% if (user.is_admin):%> > checked > <% end %> > > > > > <%end%> > > <% > print "

¹²ÓмǼ %sÌõ£¬·ÖΪ%sÒ³£¬Ã¿Ò³%sÌõ¼Ç¼ £¬µ±Ç°µÚ%sÒ³
" % > (pager.totleElementNumber,pager.totlePageNum,pager.pageSize, > pager.currentPN) > %> > <% if pager.havePrev():%> > <% print "> > href='/digyn/control/userControl.ks/userManage?act=list&pageNumber;=%s'>ÉÏÒ»Ò³" > % (pager.currentPN-1) %> > <%end%> > <% if pager.haveNext():%> > <% print "> > href='/digyn/control/userControl.ks/userManage?act=list&pageNumber;=%s'>ÏÂÒ»Ò³" > % (pager.currentPN+1) %> > <%end%> > > > > > > }}} > > > ·ÖÒ³Æ÷£º`pager.py:` > {{{#!python > import math > class Pager(object): > def __init__(self,nowList,currentPN,pageSize,totleElementNumber): > self.nowList = nowList > self.currentPN = currentPN > self.pageSize = pageSize > self.totleElementNumber = totleElementNumber > > def getTotlePageNum(self): > return int(math.ceil(self.totleElementNumber / float(self.pageSize > ))) > totlePageNum = property(fget=getTotlePageNum,doc="return totle page > number") > def havePrev(self): > if self.currentPN >1: > return True > else: > return False > def haveNext(self): > if ((self.currentPN*self.pageSize)> return True > else: > return False > }}} > > [ ±¾Ìû×îºóÓÉ lvscar ÓÚ 2007-12-17 00:46 ±à¼­ ] > > = ·´À¡ = > [[PageComment2]] > > > -- > '''Time is unimportant, only life important! > ¹ý³Ì¸Ä½øÄËÊÇ¿ªÊ¼´ßÉú¿É´ÙÉú¿¿Æ×µÄÈ˵Ä×éÖ¯! > '''http://zoomquiet.org > ²© @ http://blog.zoomquiet.org/pyblosxom/ > ά @ http://wiki.woodpecker.org.cn/moin/ZoomQuiet > ¶¹ @ http://www.douban.com/people/zoomq/ > ¿´ @ http://zoomq.haokanbu.com/ > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ > Pls. usage OOo to replace M$ Office. http://zh.openoffice.org > Pls. usage 7-zip to replace WinRAR/WinZip. http://7-zip.org > You can get the truely Freedom 4 software. > _______________________________________________ > python-chinese > Post: send python-chinese在lists.python.cn > Subscribe: send subscribe to python-chinese-request在lists.python.cn > Unsubscribe: send unsubscribe to python-chinese-request在lists.python.cn > Detail Info: http://python.cn/mailman/listinfo/python-chinese -------------- 下一部分 -------------- Ò»¸öHTML¸½¼þ±»ÒƳý... URL: http://python.cn/pipermail/python-chinese/attachments/20071217/692b7b91/attachment.html


[导入自Mailman归档:http://www.zeuux.org/pipermail/zeuux-python]

2007年12月17日 星期一 09:15

朽木klutz chumpklutz在gmail.com
星期一 十二月 17 09:15:27 HKT 2007

¿ÉÒԌWÁ•django»òrails¸ãЩÃüÁîÉú³Éһ٘Ë×¼»¯Ä¿ä›½Y˜‹,¿ÉÒÔ׌´ó¼ÒʹÓÃÆðíº††ÎһЩ

ÔÚ07-12-17£¬Ðàľklutz <chumpklutz在gmail.com> дµÀ£º
>
> ŒWÁ•Ö®
>
> ÔÚ07-12-17£¬Zoom. Quiet <zoom.quiet在gmail.com> дµÀ£º
> >
> > ¸Ðл lv yi <lvscar在gmail.com> µÄ·ÖÏí£¡
> > http://wiki.woodpecker.org.cn/moin/KarrigellStorm
> >
> > = ×°ÔÚÍÆ³µÀïµÄ±©·çÑ© =
> > * ԭʼÎÄÕÂ:http://bbs.chinaunix.net/thread-1030014-1-1.html ^2007-12-16
> > 23:02 ^
> >
> > »îÔÚÕâ¸öµ½´¦web n.0 µÄʱ´ú£¬ÎÞÂÛ¹¤×÷»¹Êǰ®ºÃ£¬³ö¸öwebСÏîÄ¿£¬ÕâÐèÇó¶ÔÔÛ³ÌÐòԱʵÔÚÊÇÌ«ÆÕ±éÁË¡£
> > ×÷Ϊpython°®ºÃÕߣ¬Äã»áÔӰ죿
> > °Ñdjango×ÊÁÏÕÒ³öÀ´»¨¸ö3¸öÔ£¬ÊìϤËüÅÓ´óµÄ½á¹¹¡£¶ÀÌØµÄORM£¬ºÍ¸÷ÖÖtaglib £¿
> > ¹þ£¬°³ÃÇÓÖ²»ÊÇ¿ÉÁ¯µÄrubyÓû§¡£
> > ÄãÍêÈ«¿ÉÒÔÔÚpythonÊÀ½çÀïÐÅÊÖÄéÆð×îÊʺÏÄãµÄ×é¼þ£¬ÒÔ×î¿ìµÄËٶȹ¹½¨ÆðÄã×Ô¼ºµÄweb¿ò¼Ü¡£
> >
> > Èç¹ûÄãµÄÏîÄ¿·ûºÏÒÔÏÂÌõ¼þ£¬Äã»òÐí¿ÉÒÔ¿¼ÂÇ karrigell + storm
> >
> >
> >    * ²»ÐèÒª³ÐÔØº£Á¿Óû§²¢·¢·ÃÎÊ
> >    * ¿ìËÙÉÏÊֵĿª·¢¹ý³Ì
> >    * ÐèÒª¸ß¿É¶ÁÐÔºÍÒ×ÓÚά»¤µÄ´úÂë
> >    * ÑÓÐøÄãÔÚjavaÖÐϰ¹ßµÄmvc˼Ïë
> >    * ʹÓÃÈËÐÔ»¯µÄORM½øÐÐdb²Ù×÷
> >    * ¼òµ¥µÄ²¿Êð²½Öè
> >
> >
> > == ÏÈÊÇÒ»µã±³¾°: ==
> >
> > === Karrigell£º ===
> >
> > Karrigell  ÊÇÇáÁ¿¼¶µÄweb¿ò¼Ü¡£Áé»î£¬Ö±¹Û£¬Êý¾Ý¿â£¯ORM£¯Ä£°åÒýÇæ ¶ÀÁ¢¡£
> >
> > Karrigell ºÜÈÝÒ×ÉÏÊÖ£¬»¨¸ö1Сʱ°ÑtutorialÒ»¿´£¬¾ÍÄÜÓÃhtmlºÍpython´úÂëÆ´³ö¸ö¼òµ¥µÄweb³ÌÐò³öÀ´¡£
> >
> > Karrigell Ö§³Ö¶àÖÖ·½Ê½»ìºÏpython´úÂëºÍhtml¡£ÎÞÂÛÄãÒÔǰÓÐÄÄÒ»Åɵı³¾²£¬¶¼ÄÜÔÚkarrigellÀïÑÓÐøÄãµÄ¾­ÑéºÍϰ¹ß¡£
> >
> > Karrigell ²¿Êð¼òµ¥¡£ÓÐpythonÔËÐл·¾³£¬¾ÍÄÜÈÃËüÅܵ϶³©¡£
> >
> > Karrigell´úÂë³ÉÊì¡£ 5ÄêÀ´Karrigell»ù±¾±£³Ö×ŰëÄêÒ»¸ö°æ±¾ËÙ¶ÈÔڳɳ¤¡£
> >
> >
> > === Storm   ===
> >
> > Storm ÊÇÓÉCanonical¿ª·¢µÄÒ»Ì× Python ORM¿â£¬ÓÃÔÚÖ§³Ö×ÅubunutµÄLaunchpadÏîÄ¿ÉÏ¡£
> >
> > ÒÔÏÂÊÇStormµÄһЩÁÁµã£¨·­Òë×Ôstorm¹Ù·½ÍøÕ¾£©£º
> >
> > ¸É¾»µÄÇáÁ¿¼¶APIʹµÃStormµÄѧϰÉÏÊÖ¹ý³ÌÏà¶ÔÇáËÉ¡£»ùÓÚStormµÄ´úÂëÒ²ÓÐ×ÅÓѺõÄά»¤ÐÔ.
> >
> > StormÓɲâÊÔÇý¶¯Ä£Ê½¿ª·¢,ÈκÎÒ»ÐÐû¾­¹ý²âÊԵĴúÂë¶¼±»ÈÏΪ´æÔÚbug¡£
> >
> > Storm ÖеÄModelÀà ²»ÐèÒªÌØ±ðµÄ¹¹ÔìÆ÷£¬Ò²²»ÐèÒªÇ¿ÖÆÊ¹ÓÃרÃŵĻùÀà¡£
> >
> > Storm ÕûÌåÉè¼ÆµÃºÜºÃ¡£ £¨´úÂëÖв»Í¬µÄ²¿·ÖÓÐ×ŷdz£ÇåÎúµÄ±ß½ç¡£¹«¹²apiÊýÁ¿Ð¡ºÍÒâÒåÃ÷È·£©
> >
> > Storm´ÓÒ»¿ªÊ¼ÒÔͬʱ֧³ÖÇáÁ¿¼¶£¨SQLite£©ºÍÖØÁ¿¼¶£¨PostgreSQL £¯ MYSQL£©¶øÉè¼Æ¡£
> >
> > Storm´úÂë×ñÑ­KISSÔ­Ôò±àд£¬´úÂë¼òµ¥Ò×¶Á£¬µ÷ÊÔ·½±ã¡£
> >
> > Storm´ÓÒ»¿ªÊ¼¾ÍΪ×Åͬʱ֧³ÖµÍ¶ËС³ÌÐòºÍ¸ß¶Ë£¨¶à¸öÊý¾Ý¿â£¬Ê®ÒÚ¼¶Êý¾ÝÁ¿£©¶øÉè¼Æ¡£
> >
> > === Ïà¹ØÑ§Ï°×ÊÁÏ ===
> > karrigellºÍstorm ¶¼ºÜpythonic£¬¿´Íêtoturial »ù±¾¾ÍÄÜÉÏÊÖ.
> > ÏëÉîÈëÁ˽â¾ÍÖ±½Ó¿´´úÂë¡£´úÂë¾ù¸É¾»Õû½à£¬×¢ÊÍÏ꾡¡£¿´ÕâÀàÏîÄ¿µÄÂëÊÇÏíÊܰ¡£º
> >
> > * karrigellµÄtoturialµØÖ·£ºhttp://karrigell.sourceforge.net/en/front.htm
> > * ChumpKlutz ÐàľÐÖ¶ÔÕâÕâ·Ýtoturial½øÐÐÁË·­£¬¿ÉÒÔµ½ËûµÄblog ²é¿´£º
> > http://blog.csdn.net/chumpklutz/
> >
> > * stormµÄtoturialµØÖ·£ºhttps://storm.canonical.com/Tutorial
> > * Ŀǰ»¹Ã»ÓÐÖÐÎİ棬°³ÕùÈ¡ÏÂÔÂÍê³ÉÕâ·ÝtoturialµÄ·­Òë.
> >
> >
> > == ¶ÔKarrigellµÄMVC»¯¹æ·¶ ==
> > karrigell
> > ¸½´øµÄdemoÊÇѧϰkarrigell×îºÃµÄ;¾¶¡£KarrigellµÄ¸÷ÖÖÓ÷¨¶¼ÔÚÕâÆß°Ë¸ödemoÖÐÓо«²ÊµÄÌåÏÖ¡£µ«»òÐíÊÇ×÷Õß¿ÌÒâÏëͨ¹ýÕ⼸¸ö
> > demo ÌåÏÖ³ökarrigellµÄÁé»î£¬phi£¬hip£¬ks »ìºÏÆðÀ´ÂùÈÝÒ×°ÑÈ˸ãÔΡ£¶øÇÒ¸½´øµÄ¼¸¸ödemo
> > ´úÂë×éÖ¯¶¼ºÜËÉÉ¢£¬ÍùÍù¾ÍÊǰÑÒ»¶Ñphi,hip,ks,js,gif·ÅÔÚÒ»ÆðÁËÊ¡£Èç¹û֮ǰ¿´¹ýrails»òdjango
> > ¿ÉÄܻ᲻̫ÊÊÓ¦karrigell demoÖеÄÕâÖÖÁèÂҸС£
> >
> > ¹þ£¬±ð»Å£¬Èç¹ûÔ¸Ò⣬ÄãÍêÈ«¿ÉÒÔ°ÑÄãµÄÏîÄ¿°´ÕÕÌìÌõËÆµÄmvc½á¹¹À´×éÖ¯¡£¼ÓÉÏÉÙÐí¹æ·¶£¬karrigellÒ²ÄÜÐã³örailsÄÇÑùµÄÐÎʽÖ÷ÒåÃÀ¡£
> >
> > ÏÂÃæÊÇ£¬ÎÒµÄÒ»¸öСÏîÄ¿µÄ
> > === ´úÂë°²ÅÅ£º ===
> > ÔÚ karrigell webapps Ŀ¼Ï£¬ÓÃÄãϲ»¶µÄÃû×ÖÃüÃûÄãµÄkarrigell¹¤³Ì¡£
> > ¹¤³ÌĿ¼Ï£¬Ð½¨£º{{{
> > conf/  control/   model/  service/  test/  util/  web/  Õ⼸¸öĿ¼£¬
> > ÒÔ¼° index.pih   ºÍ __init__.py
> > }}}
> > ÎÒµÄϰ¹ßÊǰÑ`Ŀ¼ºãÁ¿`£¬ºÍÊý¾Ý¿âÅäÖ÷ÅÔÚ conf Ï¡£
> > * ORM ¶ÔÏó ·ÅÔÚ model Ŀ¼£»
> > * serviceĿ¼Ï·ÅÖÃÒµÎñ´úÂ룻
> > * utilÀï·ÅÈëµÚÈý·½¿â£»
> > * testÀïдµãС²âÊÔ´úÂë¡£
> > * ËùÓÐǰ̨´úÂ룬¶¼·Åµ½webĿ¼ÀËùÒÔwebĿ¼Ï¿ÉÒÔÔÙн¨¼¸¸öjs/ css/ uploadFiles/  ÕâÑùµÄĿ¼¡£
> > * webĿ¼Ï£¬Ö»Ð´ºÍǰ̨չÏÖÏà¹ØµÄ´úÂ룬¸ù¾ÝÒ³ÃæµÄ¸´Ôӳ̶ȣ¬ÔÚpihºÍhipÖÐÑ¡Ôñ¡£
> > * contorlĿ¼Ï£¬Ö»Ð´Ò³ÃæÌø×ª£¬ÎªwebĿ¼ÏµÄpihºÍhipÌṩ±äÁ¿ ºÍµ÷ÓÃÏà¹ØÒµÎñ·½·¨µÄ´úÂë¡£ ksÊÇ×îºÃµÄÑ¡Ôñ¡£
> > ͬһ¸ö¶ÔÏ󣬲»Í¬µÄwebÐÐΪ¡£¿ÉÒÔдÔÚ³ÉÒ»¸öksÖеĶà¸ö·½·¨¡£
> >
> > tips:: ks Öв»ÄÜÖ±½Ó²¶»ñÒýÈë·½·¨Å׳öµÄÒì³££¬ÒòΪÒì³£ÔÚ core.k_script  ÀïÒѾ­±»²¶»ñ²¢×öÁË´¦Àí¡£
> > ÎҵĽâ¾ö·½·¨ÊÇ£¬°ÑËùÓÐ×Ô¼ºÓõ½µÄÒì³£µÄ×Ô¶¨Ò常Àà Ìí¼Óµ½
> > core/k_script.py 154ÐÐ×óÓÒ  Ö±½ÓÅ׳ö²¶»ñÒì³£µÄ except ×Ö¾ä²ÎÊýÀï¡£
> > È»ºóÔÙ°ÑËùÓÐÓõ½µÄÒì³£ÒýÈë modules/mod_ks.py ÖС£
> >
> >
> > === ¼¯³ÉStorm£º ===
> > karrigell ¼¯³Éstorm¿ÉÒÔ˵ÊǷdz£·½±ã¡£ °Ñstorm ½âѹºó£¬·Åµ½ karrigellµÄ /databases Ŀ¼¡£
> > ÔÚÎÒÃǵÄÏîÄ¿µÄ conf/ Ŀ¼Ï ½¨Á¢¸östorm_conf.py µÄmodule ÄÚÈÝÈçÏÂ:
> > {{{#!python
> > fromdatabases.storm.locals import *
> > db_url = "postgres://lvs:car@localhost/digyn_dev"
> >
> > database = None
> > store = None
> > def getStore():
> >    global store
> >    if store == None:
> >        store = Store(getDatabase())
> >
> >    return store
> >
> >
> > def getDatabase():
> >    global database
> >    if database == None:
> >        database = create_database(db_url)
> >    return database
> >
> > #ÒòΪ²ÉÓÃÁËmodule È«¾Ö±äÁ¿¡£ÒýÓôËmoduleÔÚ×îºÃͳһΪ¾ø¶Ô°üÃûÒýÓÃ
> > }}}
> >
> > È»ºó£¬ÎÒÃǾͿÉÒÔÔÚserviceÀï ÏñÕâÑù×ÔÈ»µÄ½øÐÐÊý¾ÝµÄ³Ö¾Ã»¯²Ù×÷£º
> > {{{#!python
> > from webapps.digyn.model.orm_models import *
> > from webapps.digyn.util.pager import Pager
> > from webapps.digyn.conf import storm_conf
> > store = storm_conf.getStore()
> > def add(moduleId,title,bugInfo,findDate,findUserId):
> >    bug = Bug(moduleId,title,findDate,findUserId,bugInfo)
> >    bug.bug_state = constantValue.bugState_new
> >    store.add(bug)
> >    store.commit()
> >    return bug.id
> >
> > def get(bugId):
> >    return store.get(Bug,bugId)
> >
> > def getBugsPagerForModule(moduleId,bugState,pageNumber=1,pageSize=10):
> >    """»ñÈ¡ÌØ¶¨Ä£¿éÏÂÌØ¶¨×´Ì¬µÄbug"""
> >    resList = store.find(Bug,Bug.module_id == moduleId,Bug.bug_state
> > == bugState).order_by(Bug.id <http://bug.id/>)
> >    presList = resList[(pageNumber-1)*pageSize:pageNumber*pageSize]
> >    return Pager(presList,pageNumber,pageSize,resList.count())
> >
> > }}}
> > [ ±¾Ìû×îºóÓÉ lvscar ÓÚ 2007-12-17 01:12 ±à¼­ ]
> >
> > === ºǫ́µ½Ç°Ì¨µÄ´úÂëÆ¬¶Î ===
> >
> > ´Óºǫ́µ½Ç°Ì¨ÊµÏÖÓû§¹ÜÀí¹¦ÄܵĴúÂëÆ¬¶Î£º
> >
> > storm ORM ¶ÔÏó  `orm_models.py:`
> > {{{!python
> > import md5
> > from databases.storm.locals import *
> >
> > class User(Storm):
> >    __storm_table__='users'
> >    id = Int(primary=True)
> >    password =  RawStr()
> >    name = Unicode()
> >    info = Unicode()
> >    is_admin = Bool()
> >    manageProjects = ReferenceSet('User.id <http://user.id/>','
> > Project.manager_id')
> >    joinProjects =
> > ReferenceSet(id,'_UserProjectRelation.user_id','_UserProjectRelation.project_id','
> > Project.id <http://project.id/>')
> >    joinModules =
> >
> > ReferenceSet(id,'_UserModuleRelation.user_id','_UserModuleRelation.module_id','
> > Module.id <http://module.id/>')
> >
> >    def __init__(self,name,password,is_admin=False):
> >        self.name = name
> >        self.password = password
> >        self.is_admin = is_admin
> >
> >    def __setattr__(self,name,value):
> >        if name == 'password':
> >            #self.__dict__['password'] = value   #ÉèÖµÊÇͨ¹ýStorm
> > ÊôÐÔÀàµÄ__set__·½·¨£¨ÖØÔØ '='²Ù×÷·û )ʵÏֵġ£¸Ä±äinstanceÖеÄÖµ£¬±ä»¯²»»á±»storm²ì¾õ
> >            processedPassword = md5.new (value).digest()
> >            User.password.__set__(self,processedPassword)
> >        else:
> >            super(User,self).__setattr__(name,value)
> > }}}
> >
> > Ëä˵ Storm orm¶ÔÏó²»ÐèÒª¼Ì³ÐÌØ±ðµÄ¸¸À࣬µ«¼Ì³ÐStormÀà»á´øÀ´Ò»¸ö·½±ã£¬
> > ÔÚ½¨Á¢¶ÔÏó¹ØÏµÊ±£¬¿ÉÒÔÓÃ×Ö·û´®ÒýÓÃÆäËûÀà¡£
> >
> > Service²ã´úÂ룺`userService.py:`
> > {{{#!python
> > import md5
> > from webapps.digyn.conf import storm_conf
> > from common.exception import *
> > from webapps.digyn.model.orm_models import User
> > from webapps.digyn.util.pager import Pager
> >
> > store = storm_conf.getStore()
> >
> > def addUser(name,password):
> >    if checkUserNameUsed(name):
> >        raise NameDuplicate, name
> >    user = User(name,password)
> >    store.add(user)
> >    store.commit ()
> >
> > def checkUserNameUsed(name):
> >    if store.find(User,User.name <http://user.name/> == name).one():
> >        return True
> >    else:
> >        return False
> >
> > def deleteUser(userId):
> >    user = get(userId)
> >    store.remove(user)
> >    store.commit()
> >
> > def loginValidate(name,password):
> >    password = md5.new(password).digest()
> >    user = store.find(User,User.name <http://user.name/> == name,
> > User.password == password).one()
> >    if user:
> >        return user
> >    else:
> >        return False
> > def get(userId):
> >    return store.get(User,int(userId))
> >
> > def getAllUser():
> >    return store.find(User)
> >
> > def getManageProjects(userId):
> >
> >    user = store.get(User,int(userId))
> >    projectList = []
> >    for p in user.manageProjects:
> >        projectList.append(p)
> >    return projectList
> >
> > def getjoinProjects(userId):
> >    user = store.get(User,int(userId))
> >    projectList = []
> >    for p in user.joinProjects:
> >        projectList.append(p)
> >    return projectList
> > def assignAdmin(act,userId):
> >    user = get(userId)
> >    if act == 'add':
> >        user.is_admin = True
> >    elif act == 'remove':
> >        user.is_admin = False
> >    store.commit()
> >
> > def getUserPager(pageNumber =1,nameQueryStr = None,pageSize=10):
> >        if (nameQueryStr and len(nameQueryStr) > 0):
> >            resList = store.find(User,User.name.like
> > (u"%"+nameQueryStr+u"%"))
> >        else:
> >            resList = store.find(User)
> >        resList = resList[(pageNumber-1)*pageSize:pageNumber*pageSize]
> >        return Pager(resList,pageNumber,pageSize,resList.count())
> > }}}
> >
> >
> > ¶¥Â¥ÄǸötipsµÄÒâÒ壬¾ÍÔÚÓÚ¿ÉÒÔÈÃService²ãÖÐдaddUser·½·¨Ê±£¬ÎÒÃÇ¿ÉÒÔÖ±½ÓÅ׳öÒ»¸ö×Ô¶¨ÒâÒì³££¬ÈÃcontrol²ã´úÂë¿ÉÒÔд³ÉÏÂÃæÕâÖÖ¸ñʽ£º{{{
> >     try:
> >        userService.addUser(name,password)
> >    except NameDuplicate,userName:
> >        Include("/digyn/web/user/register.pih",flash="Óû§ %s ÒѾ­´æÔÚ"
> > %str(userName))
> >        return
> >    Include("/digyn/index.pih",flash="%s ÄãµÄÕʺÅÒÑÌí¼Ó£¬ÇëµÇ¼"  % ( name.encode
> > ('utf-8')))
> > }}}
> > [ ±¾Ìû×îºóÓÉ lvscar ÓÚ 2007-12-17 00:25 ±à¼­ ]
> >
> >
> > === Control²ã´úÂë ===
> > * `userControl.ks`:
> > {{{#!python
> > #-*- coding:utf-8 -*-
> > from webapps.digyn.service import userService
> > from common.exception import *
> > PageSize = 10
> >
> > def register(name,password,password_again):
> >    name = unicode(name,'utf-8')
> >    if(password != password_again):
> >        Include("/digyn/web/user/register.pih",flash="Á½´ÎÊäÈëµÄÃÜÂë²»·û")
> >        return
> >    try:
> >        userService.addUser(name,password)
> >    except NameDuplicate,userName:
> >        Include("/digyn/web/user/register.pih",flash="Óû§ %s ÒѾ­´æÔÚ"
> > %str(userName))
> >        return
> >    Include("/digyn/index.pih",flash="%s ÄãµÄÕʺÅÒÑÌí¼Ó£¬ÇëµÇ¼"  % (name.encode
> > ('utf-8')))
> >
> > def login(name,password):
> >    name = unicode(name,'utf-8')
> >    user = userService.loginValidate (name,password)
> >    if user:
> >        session = Session()
> >        session.userId = user.id
> >        if user.is_admin:
> >            session.is_admin = True
> >        else:
> >            session.is_admin = False
> >        Include("/digyn/web/user/userIndex.pih",user=user)
> >        return
> >    else:
> >        Include("/digyn/web/user/login.pih" ,flash="¸ÃÓû§²»´æÔÚ»òÃÜÂë´íÎó")
> >
> > def logout():
> >    Session().close()
> >    raise HTTP_REDIRECTION,"/digyn"
> >
> > def userManage(act,pageNumber=1):
> >    pageNumber  = int(pageNumber)
> >    _checkIsAdmin()
> >
> >    if act == "list":
> >        _getUserPager(pageNumber)
> >
> > def _getUserPager(pageNumber ,nameQueryStr = None,pageSize=PageSize):
> >    userPager = userService.getUserPager
> > (int(pageNumber),pageSize=pageSize)
> >    Include("/digyn/web/admin/userList.pih",userPager=userPager)
> >
> > def assignAdmin(act,userId):
> >    """É趨Óû§ÊÇ·ñΪϵͳ¹ÜÀíÔ±"""
> >    _checkIsAdmin()
> >    userId = int(userId)
> >    if act == "add":
> >        userService.assignAdmin("add",userId)
> >    elif act == "remove":
> >        userService.assignAdmin("remove",userId)
> >    else:
> >        print "erroe"
> >        return
> >    print "success"
> >
> > def deleteUser(userId):
> >    _checkIsAdmin()
> >    userId = int(userId)
> >    userName = userService.get(userId).name
> >    userService.deleteUser(userId)
> >    userPager = userService.getUserPager(1,pageSize=pageSize)
> >    Include("/digyn/web/admin/userList.pih",userPager=userPager,flash="Óû§
> >
> > %s ÒѾ­É¾³ý" %(userName.encode('utf-8')))
> >
> > def _checkUserLogin():
> >    if not hasattr(Session(),'userId'):
> >        Session().close()
> >        Include("/digyn/web/user/login.pih",flash="ÇëÏȵǼ")
> >        raise SCRIPT_END
> > def _checkIsAdmin():
> >    if(( not hasattr(Session(),'is_admin')) or (not Session().is_admin)):
> >        Session().close()
> >        Include("/digyn/index.pih",flash="Äãδ±»ÊÚȨ·ÃÎÊ")
> >        raise SCRIPT_END
> > }}}
> >
> > Control²ãÒ»¸ö·½·¨¶ÔÓ¦ Ò»¸öweb¶¯×÷£¬±íµ¥²ÎÊýÃûÖ±½ÓÓÃ×ö·½·¨²ÎÊý¡£ ͨ¹ýurlÀ´¾ö¶¨µ÷ÓÃÄĸö·½·¨
> > ÀýÈçÏÂÃæµÄ±íµ¥ÊµÏÖÓû§µÇ¼£º
> > {{{
> > 
> > Óû§Ãû
> > ÃÜÂë
> > > >
> > }}} > > Include ºÍ raise HTTP_REDIRECTION ÕâÁ½ÖÖʵÏÖurlתÏòµÄ·½·¨ÀàËÆ java servlet±à³ÌÖÐµÄ > > sendRedirect ºÍ forward > > > > ͨ¹ý_checkUserLogin £¯_checkIsAdmin Ìá¸ß°²È«ÐÔ£¬ÊµÏÖ railsÖÐµÄ before filter µÄЧ¹û¡£ > > > > [ ±¾Ìû×îºóÓÉ lvscar ÓÚ 2007-12-17 00:40 ±à¼­ ] > > > > === View ²ã´úÂë === > > > > Óû§Áбí½çÃæ`userList.pih:`{{{ > > > > > > project digyn > > > > > > type="text/css" /> > > > > > > > > > > > > <% > > Include("/digyn/web/banner.frag") > > Include("/digyn/web/side.frag.pih") > > %> > >
> > > > <% > > pager = userPager > > > > %> > >
> > > > Óû§Ãû×ÖÏÖ²ÎÓëÏîĿɾ³ýÊÚȨΪ¹ÜÀíÔ± > > > > <%for user in userPager.nowList: %> > > > > <%=user.name.encode('utf-8')%> > > > > > > > > <% for p in user.joinProjects :%> > > <%=p.name.encode('utf-8')%>  > > <% end %> > > > > > > > > > > <% if user.manageProjects.count() >1 :%> > > ÏîÄ¿¸ºÔðÖÐ > > <% end %> > > <% else :%> > > > > > > onclick="openUrlWithConfirm('/digyn/control/userControl.ks/deleteUser?userId=<%= > > user.id%>')">ɾ³ý¸ÃÓû§ > > <% end %> > > > > > > > > value="<%=user.id%>" > > <% if user.id == Session().userId: > > print "disabled" > > %> > > <% else: > > print "onclick='changeState(this)'" > > %> > > <% if (user.is_admin):%> > > checked > > <% end %> > > > > > > > > > <%end%> > > > > <% > > print "

¹²ÓмǼ %sÌõ£¬·ÖΪ%sÒ³£¬Ã¿Ò³%sÌõ¼Ç¼ £¬µ±Ç°µÚ%sÒ³
" % > > (pager.totleElementNumber ,pager.totlePageNum,pager.pageSize, > > pager.currentPN) > > %> > > <% if pager.havePrev():%> > > <% print "> > href='/digyn/control/userControl.ks/userManage?act=list&pageNumber;=%s'>ÉÏÒ»Ò³" > > > > % (pager.currentPN-1) %> > > <%end%> > > <% if pager.haveNext():%> > > <% print "> > href='/digyn/control/userControl.ks/userManage?act=list&pageNumber;=%s'>ÏÂÒ»Ò³" > > > > % (pager.currentPN+1) %> > > <%end%> > > > > > > > > > > > > }}} > > > > > > ·ÖÒ³Æ÷£º`pager.py:` > > {{{#!python > > import math > > class Pager(object): > > def __init__(self,nowList,currentPN,pageSize,totleElementNumber): > > self.nowList = nowList > > self.currentPN = currentPN > > self.pageSize = pageSize > > self.totleElementNumber = totleElementNumber > > > > def getTotlePageNum(self): > > return int(math.ceil (self.totleElementNumber / float( > > self.pageSize))) > > totlePageNum = property(fget=getTotlePageNum,doc="return totle page > > number") > > def havePrev(self): > > if self.currentPN >1: > > return True > > else: > > return False > > def haveNext(self): > > if ((self.currentPN*self.pageSize)> > return True > > else: > > return False > > }}} > > > > [ ±¾Ìû×îºóÓÉ lvscar ÓÚ 2007-12-17 00:46 ±à¼­ ] > > > > = ·´À¡ = > > [[PageComment2]] > > > > > > -- > > '''Time is unimportant, only life important! > > ¹ý³Ì¸Ä½øÄËÊÇ¿ªÊ¼´ßÉú¿É´ÙÉú¿¿Æ×µÄÈ˵Ä×éÖ¯! > > ''' http://zoomquiet.org > > ²© @ http://blog.zoomquiet.org/pyblosxom/ > > ά @ http://wiki.woodpecker.org.cn/moin/ZoomQuiet > > ¶¹ @ http://www.douban.com/people/zoomq/ > > ¿´ @ http://zoomq.haokanbu.com/ > > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ > > Pls. usage OOo to replace M$ Office. http://zh.openoffice.org > > Pls. usage 7-zip to replace WinRAR/WinZip. http://7-zip.org > > You can get the truely Freedom 4 software. > > _______________________________________________ > > python-chinese > > Post: send python-chinese在lists.python.cn > > Subscribe: send subscribe to python-chinese-request在lists.python.cn > > Unsubscribe: send unsubscribe to python-chinese-request在lists.python.cn > > Detail Info: http://python.cn/mailman/listinfo/python-chinese > > > -------------- 下一部分 -------------- Ò»¸öHTML¸½¼þ±»ÒƳý... URL: http://python.cn/pipermail/python-chinese/attachments/20071217/794244b9/attachment-0001.htm


[导入自Mailman归档:http://www.zeuux.org/pipermail/zeuux-python]

如下红色区域有误,请重新填写。

    你的回复:

    请 登录 后回复。还没有在Zeuux哲思注册吗?现在 注册 !

    Zeuux © 2025

    京ICP备05028076号