在金字塔中创建动态 class 视图
Create dynamic class-views in pyramid
我正在尝试减少在 Pyramid 视图中编写的代码,并且正在尝试通过工厂函数来完成。
因此,我的 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)
原因很明显,我最终会得到许多可以利用相同 class 功能的 classes,我想减少我的代码编写。如果您要求我改为使用继承,那么我会被困在如何配置派生的 classes 以具有参数化装饰器(如 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()
如有任何帮助,我们将不胜感激,在此先致谢!
您的代码无法正常工作的最可能原因是 Pyramid 在启动时执行的 scan 过程的细节,以查找和处理所有 @view_config
装饰器。一方面,@view_config
文档字符串说:
``view_config`` will work ONLY on module top level members
because of the limitation of ``venusian.Scanner.scan``.
所以我猜要么你的 类 在启动过程中创建得太晚了,要么你动态生成的 类 中的某些东西让金星人感到困惑。如果您查看 venusian
的源代码,您可能会找到原因。
但是,我想指出的是,这种方法让我觉得有点递归...... Pyramid 中有一些方法可以在没有任何装饰器的情况下注册视图。然后 Pyramid 作者在其之上添加了一层 "syntax sugar" 以简化最常见的用例并能够通过简单地添加装饰器来注册视图。然后你开始与那些装饰器战斗,以便能够通过看起来像函数调用的方式注册视图:)
看看 pyramid.config.Configurator.add_view() - 它看起来已经很像你的 "factory function" 但如果你愿意,你可以围绕它编写一个简单的包装器。
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')
我正在尝试减少在 Pyramid 视图中编写的代码,并且正在尝试通过工厂函数来完成。
因此,我的 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)
原因很明显,我最终会得到许多可以利用相同 class 功能的 classes,我想减少我的代码编写。如果您要求我改为使用继承,那么我会被困在如何配置派生的 classes 以具有参数化装饰器(如 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()
如有任何帮助,我们将不胜感激,在此先致谢!
您的代码无法正常工作的最可能原因是 Pyramid 在启动时执行的 scan 过程的细节,以查找和处理所有 @view_config
装饰器。一方面,@view_config
文档字符串说:
``view_config`` will work ONLY on module top level members
because of the limitation of ``venusian.Scanner.scan``.
所以我猜要么你的 类 在启动过程中创建得太晚了,要么你动态生成的 类 中的某些东西让金星人感到困惑。如果您查看 venusian
的源代码,您可能会找到原因。
但是,我想指出的是,这种方法让我觉得有点递归...... Pyramid 中有一些方法可以在没有任何装饰器的情况下注册视图。然后 Pyramid 作者在其之上添加了一层 "syntax sugar" 以简化最常见的用例并能够通过简单地添加装饰器来注册视图。然后你开始与那些装饰器战斗,以便能够通过看起来像函数调用的方式注册视图:)
看看 pyramid.config.Configurator.add_view() - 它看起来已经很像你的 "factory function" 但如果你愿意,你可以围绕它编写一个简单的包装器。
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')