在金字塔中创建动态类视图

时间:2015-06-16 15:22:15

标签: python templates nested pyramid factory

我正在尝试减少我的金字塔视图中的代码编写,并且我试图通过工厂函数来完成。

因此,我的 views.py

中没有这样的内容
class MyView(object):
    def __init__(self, request):
        self.request = request

    @view_config(route_name='view', renderer='templates/view.pt')
    def get(self):
        return dict(msg='Hello!')

我试着改变这样的事情:

def factory(cls_name, rtn, rndr, myfun):
    class Cls(object):
        def __init__(self, request):
            self.request = request

        @myfun(route_name=rtn, renderer=rndr)
        def get(self):
            return dict(msg='Hello!')

    Cls.__name__ = cls_name
    return Cls

MyView = factory('MyView', 'view', 'templates/view.pt', view_config)

显然,原因是我最终会拥有许多可以使用相同类功能的类,并且我希望减少我的代码编写。如果您要求我使用继承,那么我就不知道如何配置我的派生类以获得参数化装饰器(如myfun)。从本质上讲,我需要像C ++中的模板一样。

所以,即使上面的第二个片段没有产生任何错误,对我来说似乎工作得很好,当我尝试在我的测试网站中运行它时(通过用第二个片段替换第二个片段),金字塔不理解路线,所以我得到404 error。根据错误,我认为我的问题可能与金字塔如何解析 views.py 文件以查找view_config装饰器有关,但我不确定如何解决它。

我的 __ init __。py 的主要功能是这样的:

def main(global_config, **settings):
    """ This function returns a Pyramid WSGI application.
    """      
    config = Configurator(settings=settings)
    config.add_route('view', '/')
    config.scan()
    return config.make_wsgi_app()

非常感谢任何帮助,所以提前感谢所有人!

1 个答案:

答案 0 :(得分:1)

代码无效的最可能原因是Pyramid在启动时执行 scan 进程的详细信息,以查找和处理所有@view_config装饰器。首先,@view_config docstring说:

    ``view_config`` will work ONLY on module top level members
    because of the limitation of ``venusian.Scanner.scan``.

所以我猜你的类在启动过程中创建得太晚,或者动态生成的类中的某些东西会混淆venusian。如果您查看venusian的源代码,您可以找到原因。

但是,我想指出这种方法让我感觉有点递归...... Pyramid中有一些方法可以在没有任何装饰器的情况下注册视图。然后,Pyramid的作者在其上添加了一层“语法糖”,以简化最常见的用例,并能够通过简单地添加装饰器来注册视图。然后你开始对抗那些装饰器,以便能够通过看起来像函数调用来注册视图:)

看看pyramid.config.Configurator.add_view() - 它看起来非常像你的“工厂功能”,但如果你愿意的话,你可以在它周围写一个简单的包装。

class MyView(object):
    def __init__(self, request):
        self.request = request

    def get(self):
        return dict(msg='Hello!')

config.add_view(MyView, attr='get', route_name='view_cats', renderer='templates/view_cats.pt')
config.add_view(MyView, attr='get', route_name='view_dogs', renderer='templates/view_dogs.pt')