金字塔:重复数据删除相似的路线

时间:2016-12-21 18:40:10

标签: python pyramid

我的金字塔应用程序路线中的重复代码存在问题。我很确定我做错了,但不知道怎么做得更好。我们的应用程序基本上有三个“模式”,表示为URL路径的前缀。没有前缀,我们处于“prod”模式,然后我们有“/ mock”和“/ old”前缀,它们使用相同的视图和不同的后端来获取数据。

代码看起来像这样:

def routes(config):
    """Add routes to the configuration."""
    config.add_route('my_view:old', '/old/my_view')
    config.add_route('my_view:prod', '/my_view')
    config.add_route('my_view:mock', '/mock/my_view')

@view_config(route_name='my_view:mock', renderer='string')
def my_view_mock(request):
    return my_view(request, data.mock)


@view_config(route_name='my_view:prod', renderer='string')
def my_view_prod(request):
    return my_view(request, data.prod)


@view_config(route_name='my_view:old', renderer='string')
def my_view_old(request):
    return my_view(request, data.old)


def my_view(request, data):
    results = data.query(**request.json)

更糟糕的是,我们的所有端点都重复了这种模式,导致大量重复的样板代码。

我如何以某种集中的方式教我的设置金字塔并摆脱这个样板?

1 个答案:

答案 0 :(得分:1)

这是一个选择。它要求您为每个视图定义一个唯一的对象。好的部分是你可以定义那个对象然后每个路由可以不同的方式创建它...想象factory=lambda request: MyView(request, old=True)而不是为每个路由使用完全相同的MyView(request)对象。

def routes(config):
    """Add routes to the configuration."""
    config.add_directive('add_routed_resource', add_routed_resource)

    config.add_routed_resource('my_view', MyView)

def add_routed_resource(config, name, factory):
    routes = [
        ('%s:old', '/old/%s-errors', lambda request: factory(request, old=True)),
        ('%s:prod', '/%s', factory),
        ('%s:mock', '/mock/%s', lambda request: factory(request, mock=True)),
    ]
    for name_fmt, pattern_fmt in routes:
        config.add_route(
            name_fmt % name,
            pattern_fmt % name,
            factory=factory,
            use_global_views=True,
        )

class MyView:
    def __init__(self, request, old=False, mock=False):
        self.request = request
        self.old = old
        self.mock = mock

    @reify
    def data(self):
        # let's assume sqlalchemy query to load the data?
        q = self.request.db.query(...)
        if self.old:
            q = q.filter_by(old=True)
        return q.one()

@view_config(context=MyView, renderer='json')
def my_view(context, request):
    return context.data