¿Cómo hago una barra de barras opcional con WebApp2?
-
27-10-2019 - |
Pregunta
Estoy usando el nuevo WebApp2 (ahora la WebApp predeterminada en 1.6), y no he podido averiguar cómo hacer que la barra de arrastre sea opcional en un código como este:
webapp.Route('/feed', handler = feed)
He intentado /feed/?
, /feed/*
, /feed\/*
y /feed\/?
, todo fue en vano.
Solución
Para evitar la creación de URL duplicada: S en la misma página, debe usar un redirectruteute con Strict_Slash establecido en True para redirigir automáticamente /Feed /To /Feed, como este:
from webapp2_extras.routes import RedirectRoute
route = RedirectRoute('/feed', handler=feed, strict_slash=True)
Lee mas en http://webapp2.readthedocs.io/en/latest/api/webapp2_extras/routes.html
Otros consejos
No me gusta el RedirectRoute
clase porque causa un innecesario HTTP Redirección.
Basado en la documentación para clase de ruta webapp2, aquí hay una respuesta más detallada en este WebApp2.Route con una parte líder opcional hilo.
Respuesta corta
Mis patrones de ruta funcionan para las siguientes URL.
- /
- /alimento
- /alimento/
- /alimentar/crear
- /alimentar/crear/
- /feed/edit/{entity_id}
SITE_URLS = [
webapp2.Route(r'/', handler=HomePageHandler, name='route-home'),
webapp2.Route(r'/feed/<:(create/?)|edit/><entity_id:(\d*)>',
handler=MyFeedHandler,
name='route-entity-create-or-edit'),
webapp2.SimpleRoute(r'/feed/?',
handler=MyFeedListHandler,
name='route-entity-list'),
]
Espero eso ayude :-)
Así es como manejo estas rutas.
from webapp2 import Route
from webapp2_extras.routes import PathPrefixRoute
import handlers
urls = [
Route('/foo<:/?>', handlers.Foo),
Route('/bars', handlers.BarList),
PathPrefixRoute('/bar', [
Route('/', handlers.BarList),
Route('/<bar_id:\w+><:/?>', handlers.Bar),
]),
]
...
Es importante tener en cuenta que sus manejadores deberán definir *args
y **kwargs
Para lidiar con la posible barra de arrastre, que se les envía como argumento utilizando este método.
class Bar(webapp2.RequestHandler):
def get(bar_id, *args, **kwargs):
# Lookup and render this Bar using bar_id.
...
webapp2.Route
La plantilla no es una expresión regular y su valor se está escapando con re.escape
. Puede usar reglas de estilo antiguas que proporcionan plantillas de expresión regulares:
webapp2.SimpleRoute('^/feed/?$', handler = feed)
Esto funciona para mí y es muy simple. Utiliza el formato de plantilla para el enrutamiento de URI en la ruta WebApp2 clase. La barra de arrastre en este ejemplo es opcional sin redirección:
webapp2.Route('/your_url<:/?>', PageHandler)
Todo después del colon entre los Chevrons se considera un Regex: <:regex>
Si no desea usar redireccionamientos (y probablemente no lo hace), puede anular Route.match()
:
from webapp2 import Route, _get_route_variables
import urllib
from webob import exc
class SloppyRoute(Route):
"""
A route with optional trailing slash.
"""
def __init__(self, *args, **kwargs):
super(SloppyRoute, self).__init__(*args, **kwargs)
def match(self, request):
path = urllib.unquote(request.path)
match = self.regex.match(path)
try:
if not match and not path.endswith('/'):
match = self.regex.match(path + '/')
except:
pass
if not match or self.schemes and request.scheme not in self.schemes:
return None
if self.methods and request.method not in self.methods:
# This will be caught by the router, so routes with different
# methods can be tried.
raise exc.HTTPMethodNotAllowed()
args, kwargs = _get_route_variables(match, self.defaults.copy())
return self, args, kwargs
Estaba buscando una manera de hacer que la barra de trailización en la raíz de un bloque Pathprefixroute sea opcional.
Si lo ha hecho, diga:
from webapp2_extras.routes import RedirectRoute, PathPrefixRoute
from webapp2 import Route
app = webapp2.WSGIApplication([
PathPrefixRoute('admin', [
RedirectRoute('/', handler='DashboardHandler', name='admin-dashboard', strict_slash=True),
RedirectRoute('/sample-page/', handler='SamplePageHandler', name='sample-page', strict_slash=True),
]),
])
Podrás acceder /admin/
, pero no /admin
.
Como no pude encontrar una mejor solución, he agregado un redirect_to_name
a una ruta adicional, como:
from webapp2_extras.routes import RedirectRoute, PathPrefixRoute
from webapp2 import Route
app = webapp2.WSGIApplication([
Route('admin', handler='DashboardHandler', name='admin-dashboard'),
PathPrefixRoute('admin', [
RedirectRoute('/', redirect_to_name='admin-dashboard'),
RedirectRoute('/sample-page/', handler='SamplePageHandler', name='sample-page', strict_slash=True),
]),
])
Estoy interesado en mejores soluciones a este problema.
¿Debo ir a la solución de Stun y simplemente no usar redirectroute?
Se me ocurrió una especie de camino hacky. Defino la siguiente clase:
class UrlConf(object):
def __init__(self, *args, **kwargs):
self.confs = []
for arg in args:
if isinstance(arg, webapp2.Route):
slash_route = webapp2.Route(arg.template + '/', arg.handler)
self.confs += [arg, slash_route]
def __iter__(self):
for route in self.confs:
yield route
Luego configuré mis rutas como las siguientes:
MIRROR_URLS = list(UrlConf(
Route('/path/to/stuff', handler=StuffHandler, name='stuff.page'),
Route('/path/to/more/stuff', handler= MoreStuffHandler, name='more.stuff.page')
))
Si elige seguir esta ruta, obviamente puede mejorarla para que sea más flexible con otros tipos de objetos Baseroute.
No estoy familiarizado con WebApp2, pero si el primer parámetro es una expresión regular, intente:
/feed(/)?