Werkzeug direcciones URL de asignación a las vistas (a través de punto final)
Pregunta
A partir usando werkzeug, intento trazar URL (desde un archivo urls.py) a puntos de vista (de una vistas de carpeta y luego en diferentes archivos para manejar diferentes tipos de vista), mis organización de carpetas se parece a lo siguiente:
myapp/
application.py
urls.py
views/
__init__.py
common.py
places.py
...
mis urls.py archivos se parece a lo siguiente:
from werkzeug.routing import Map, Rule
url_map = Map([
Rule('/places', endpoint='places.overview')
])
y, obviamente, tengo esa pieza en el archivo de puntos de vista / places.py:
def overview(request):
mycode...
render_template('places.html', extra...)
La mayoría de los ejemplos Werkzeug muestran la utilización del decorador de exponer adjuntar direcciones URL a las vistas. Es práctico para una aplicación con 5 o 6 direcciones URL, pero puede convertirse en un infierno cuando tienes más ...
¿Hay una manera simple de correlacionar los URL directamente a los puntos de vista ???
Gracias.
Solución
Este es un ejemplo simplificado:
import views
def app(environ, start_response):
urls = url_map.bind_to_environ(environ)
request = Request(environ)
endpoint, params = urls.match()
names = endpoint.split('.')
view = views
for name in names:
if not hasattr(view, name):
__import__(view.__name__, None, None, [name])
view = getattr(view, name)
try:
response = view(request)
except werkzeug.exceptions.HTTPException, exc:
response = exc
return response(environ, start_response)
Otros consejos
import letters # our views module
url_map = Map([
Rule('/letters', endpoint=letters.index),
Rule('/letters/<int:item_id>', endpoint=letters.item),
Rule('/letters/<string:section_slug>', endpoint=letters.index),
Rule('/letters/<string:section_slug>/<int:item_id>',
endpoint=letters.item),
])
punto final puede ser cualquier cosa, incluyendo la función, por lo que sólo puede saltar la magia de importación del ejemplo de Denis
No estoy seguro de si se trata de manera preferida de abordar este problema (no he encontrado ningún ejemplo similar en werkzeug repo y todavía estoy jugando solamente con este lib), pero también es posible simplemente subclase Regla:
class CoolRule(Rule):
def __init__(self, view, *args, **kwargs):
self.view = view
super(CoolRule, self).__init__(*args, **kwargs)
def empty(self):
"""We need this method if we want to use
Submounts or Subdomain factories
"""
defaults = dict(self.defaults) if self.defaults else None
return CoolRule(self.view, self.rule, defaults, self.subdomain,
self.methods, self.build_only, self.endpoint,
self.strict_slashes, self.redirect_to,
self.alias, self.host)
_url_map = Map([
CoolRule(user.views.login, '/login', endpoint='user-login'),
CoolRule(user.views.logout, '/logout', endpoint='user-logout'),
])
def dispatch(request):
urls = _url_map.bind_to_environ(request.environ)
rule, arguments = urls.match(return_rule=True)
return rule.view(request, **arguments)
De esta manera se puede preservar la capa de abstracción de vista de nomenclatura y evitar extraña magia con 'cadena de importación'.