2016-12-21 2 views
2

J'ai un problème avec le code répété dans les routes de notre application pyramide. Je suis sûr que je me trompe, mais je ne sais pas comment faire mieux. Notre application a essentiellement trois "modes" qui sont représentés comme des préfixes au chemin de l'URL. Sans préfixe, nous sommes en mode "prod", puis nous avons les préfixes "/ mock" et "/ old" qui utilisent les mêmes vues avec des backends différents pour récupérer les données.pyramide: dédupliquer des routes similaires

Le code se révèle ressembler à ceci:

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) 

Ce qui est pire, est-ce schéma se répète pour tous nos critères d'évaluation, ce qui entraîne une tonne de code boilerplate presque-double.

Comment puis-je enseigner de manière centralisée la pyramide de ma configuration et me débarrasser de cette plaque?

Répondre

1

Eh bien, voici une option. Cela nécessite que vous définissiez un objet unique pour chaque vue. La bonne partie est que vous pouvez définir cet objet et ensuite chaque route peut le créer différemment ... Imaginez factory=lambda request: MyView(request, old=True) au lieu d'utiliser exactement le même objet MyView(request) pour chaque route.

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 
+0

Je ne vois pas ce qui différencie context.data. – bukzor

+0

Ce serait quelque chose lié à la façon dont l'objet est créé ... l'itinéraire peut contrôler cela comme je l'ai dit plus haut. Vous spécifiez une usine différente par route. –

+0

J'ai mis à jour l'exemple pour montrer comment 'MyView' pourrait être implémenté. Tout cela est juste des trucs pour vous aider à réfléchir à la façon dont vous devez résoudre votre problème. Votre exemple d'origine ne montre pas d'où proviennent les données. –