更新说明:

  1. 用户可以设定settings.py。目前kuaiboo支持在apps目录下的settings.py文件和每个app目录下的settings.py。目前apps的settings.py作为主配置文件,kuaiboo会直接导入,其它的app下的settings.py会使用__import__,然后将属性合并到settings中去。因此最终这些settings.py将合成一个,你可以在代码中导入setting。(不过对于子settings.py的处理我还在考虑是否要使用exec来处理,这样,子settings.py将不再是通过导入了,它们将在主settings.py的环境下运行,这样更象是在同一个环境下运行的。不过这块还没有想好。)
  2. expose的处理方式进行了扩充。在张沈鹏的留言中他建议能否自动映射,我理解可能有两种方式:一种是不需要expose,view函数直接映射为url,那么一方面用户无法控制哪些是可以访问,哪些是内部函数,所以我认为不使用expose不太好。当然expose只是一种实现方式,也许以后url的映射的定义会有根它的方式。另一种理解可以是只使用expose,那么当没有参数时使用自动映射。如何映射呢?我现在的方法是将view函数映射为:/appname/viewfuncname/arg1/arg2。这种方式接近web2py的,不过我没有controller一层,所以没有controller的url。那么它是怎么做的?后面会有介绍
  3. view函数的变化。原来view函数需要使用def func(req, arg1, arg2,…):,现在你不再需要req这个参数了。也就是你可以象web2py一样来定义view函数:def func(arg1, arg2):。但是你仍然可以在view函数中直接使用象request, response这样的对象,为什么,后面会有介绍。

expose的自动映射

你可以直接使用@expose来直接映射一个view方法,我是怎么做的?

def expose(rule=None, **kw):
    if callable(rule):
        f = rule
        import inspect
        args = inspect.getargspec(f)[0]
        if args :
            args = ['<%s>' % x for x in args]
        appname = f.__module__.split(‘.’)[1]
        rule = ‘/’ + ‘/’.join([appname, f.__name__] + args)
        kw['endpoint'] = f.__module__ + ‘.’ + f.__name__
        url_map.add(Rule(rule, **kw))
        return f
       
    def decorate(f):
        kw['endpoint'] = f.__module__ + ‘.’ + f.__name__
        url_map.add(Rule(rule, **kw))
        return f
    return decorate

当你使用expose时,rule参数将是function对象,因此,判断出rule是函数对象时,它将根据function本身的信息来得到它所在的模块(f.__module__)和函数名(f.__name__)。只不过f.__module__得到的是类似于apps.App.views的形式,因此要处理一下才能得到App的名字。同时一个view函数可以定义了参数,因此我还使用了inspect模块来得到定义的参数名。详情可以看它的文档,同时做一些试验。因此一个view函数会被自动映射为:/Appname/view_func_name/arg1/arg2的形式。

View函数的变化

原来view函数要定义为def func(req, arg1,…),现在你不需要第一个req的参数了。但是你仍然可以在函数内部使用request, response等对象。(至于在view函数中还能使用哪些变量我还要考虑中,可能会不断增加,这样非常接近于web2py的效果。)那么是如何实现的呢?原来我发现你可以动态修改一个函数对象的func_globals对象,如:

>>> def f():
…     print response

如果你定义上面的函数,编译不会出错,但是运行会出错。因为我们没有定义response。一种方法是定义全局的response变量,另外就是可以修改func_globals增加这个变量。如:

>>> f.func_globals['response'] = ‘hello’
>>> f()
‘hello’

可以看到执行没有问题。相当于我们定义了全局的response变量。这就相当于变量的注入,你可以直接使用。


2条评论

  1. """

    一种是不需要expose,view函数直接映射为url,那么一方面用户无法控制哪些是可以访问,哪些是内部函数,所以我认为不使用expose不太好。

    """

    有的时候一些简单的类,每一个函数都是view,这时候再去给每一个函数加上expose似乎有点繁琐.

    我的想法,用metaclass配合mixin是否可以实现这样的效果

    class XXX(Expose):

    def abc():

    return ‘xxxx’

    这时候就实现了自动导出

  2. 这个想法不错。回头我试试,这样可以支持多种view的定义方式。或者可以直接在class的方法上使用expose,都可以试一下。

发表评论

评论也有版权!