【问题标题】:Create dynamic class-views in pyramid在金字塔中创建动态类视图
【发布时间】:2015-06-16 15:22:14
【问题描述】:

我正在尝试在 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)

显然,原因是我最终将拥有许多可以利用相同类功能的类,并且我想减少我的代码编写。如果您要求我改用继承,那么我就无法将派生类配置为具有参数化装饰器(例如myfun)。本质上,我需要类似 C++ 中的模板。

所以,即使上面的第二个 sn-ps 没有产生任何错误,而且对我来说它似乎工作得很好,当我尝试在我的测试站点中运行它时(通过用第二个替换第二个 sn-p一),金字塔不理解路线,所以我得到了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()

任何帮助将不胜感激,所以提前谢谢大家!

【问题讨论】:

  • 看看这个:bitbucket.org/websauna/websauna.viewconfig - 我创建了@view_overrides 装饰器,它允许你对基类进行子类化,只更改它的一部分。动态创建类的方法非常不符合 Python 风格,并且使代码难以遵循。相反,我建议使用静态类结构,然后根据需要使用装饰器和函数修改您的类。
  • 但是 Mikko,这不会解决我使用参数化装饰器的问题,因为我仍然必须覆盖所有具有装饰器的方法,即使我只需要调用其父类对应项。我最初的问题是,既然上面的代码在语法上是正确的,那么金字塔内部的哪一部分不是
  • 我最初的问题是,既然上面的代码在语法上是正确的,并且可以做我想要的,那么它有什么问题并且金字塔忽略了它的执行?

标签: python templates nested pyramid factory


【解决方案1】:

您的代码无法正常工作的最可能原因是 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 感到困惑。如果你看一下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')

【讨论】:

  • Sergey,我的第一印象是我喜欢你对 config.add_view() 的建议。我看到的唯一特定于设计的“缺点”是这种方法将视图创建与配置结合在一起(我知道这是 Pyramid 方式的一部分,但 view_config 装饰器有助于将这两个部分解耦)。另一方面,从我的角度来看,我认为它应该能让我完成我的工作,所以我会尝试看看它是如何工作的。感谢您的建议!
猜你喜欢
  • 1970-01-01
  • 2015-11-14
  • 1970-01-01
  • 2012-11-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-03
  • 1970-01-01
相关资源
最近更新 更多