【问题标题】:pyramid: deduplicate similar routes金字塔:去重相似的路线
【发布时间】:2017-05-07 06:56:03
【问题描述】:

我在我们的金字塔应用程序的路线中遇到重复代码的问题。我很确定我做错了,但不知道如何做得更好。我们的应用程序本质上具有三种“模式”,它们表示为 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)

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

我怎样才能以某种集中的方式向金字塔传授我的设置并摆脱这个样板?

【问题讨论】:

    标签: python pyramid


    【解决方案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
    

    【讨论】:

    • 我看不出是什么让 context.data 发生变化。
    • 这与对象的创建方式有关……正如我上面所说的,路由可以控制它。您为每条路线指定不同的工厂。
    • 我更新了示例以展示如何实现MyView。这一切都只是让你思考你需要如何解决你的问题。您的原始示例也没有显示数据的来源。
    猜你喜欢
    • 2012-03-27
    • 2021-10-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-03
    • 1970-01-01
    相关资源
    最近更新 更多