Как сделать косую черту необязательной с помощью webapp2? - PullRequest
19 голосов
/ 12 января 2012

Я использую новое webapp2 (теперь веб-приложение по умолчанию в 1.6), и я не смог понять, как сделать дополнительный слеш необязательным в коде, подобном этому:

webapp.Route('/feed', handler = feed)

Я пробовал /feed/?, /feed/*, /feed\/* и /feed\/?, но все безрезультатно.

Ответы [ 9 ]

13 голосов
/ 18 января 2012

Чтобы не создавать дубликаты URL-адресов на одну и ту же страницу, следует использовать RedirectRoute со значением strict_slash, равным True, для автоматического перенаправления / feed / to / feed, например:

from webapp2_extras.routes import RedirectRoute

route = RedirectRoute('/feed', handler=feed, strict_slash=True)

Подробнее наhttp://webapp2.readthedocs.io/en/latest/api/webapp2_extras/routes.html

7 голосов
/ 19 декабря 2012

Мне не нравится класс RedirectRoute, потому что он вызывает ненужное HTTP Redirect .
На основе документации для webapp2 Route class , здесь более подробноответьте в этом webapp2.Route с необязательной ведущей частью темы.

Краткий ответ

Мои шаблоны маршрутов работают для следующих URL-адресов.

  1. /
  2. / feed
  3. / feed /
  4. / feed / create
  5. / feed / create /
  6. / 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'),
]

Надеюсь, это поможет: -)

4 голосов
/ 15 апреля 2013

Вот как я справляюсь с этими маршрутами.

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),
  ]),
]
...

Важно отметить, что ваши обработчики должны будут определить *args и **kwargs, чтобы иметь дело с потенциальным конечным слешем, который отправляется им в качестве аргумента с использованием этого метода.

class Bar(webapp2.RequestHandler):

  def get(bar_id, *args, **kwargs):
    # Lookup and render this Bar using bar_id.
    ...
2 голосов
/ 12 января 2012

webapp2.Route шаблон не является регулярным выражением, и ваше значение экранируется с помощью re.escape. Вы можете использовать старые правила стиля, которые предоставляют шаблоны регулярных выражений:

 webapp2.SimpleRoute('^/feed/?$', handler = feed)
1 голос
/ 06 марта 2014

Если вы не хотите использовать перенаправления (и, вероятно, нет), вы можете переопределить 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
1 голос
/ 08 августа 2013

Это работает для меня и очень просто. Он использует формат шаблона для маршрутизации URI в webapp2 Route class . Конечный слеш в этом примере является необязательным, без перенаправления:

webapp2.Route('/your_url<:/?>', PageHandler)

Все после двоеточия между шевронами считается регулярным выражением: <:regex>

1 голос
/ 23 мая 2013

Я искал способ сделать необязательный слеш в корне блока PathPrefixRoute необязательным.

Если у вас есть, скажите:

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),
  ]),
])

Вы сможете получить доступ к /admin/, но не /admin.

Поскольку я не мог найти лучшего решения, я добавил redirect_to_name к дополнительному маршруту, например:

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),
  ]),
])

Я заинтересован в лучших решениях этой проблемы.

Должен ли я пойти на решение Stun и просто не использовать RedirectRoute?

0 голосов
/ 07 февраля 2014

Я придумал какой-то хакерский способ.Я определяю следующий класс:

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

Затем я настраиваю свои маршруты следующим образом:

MIRROR_URLS = list(UrlConf(
    Route('/path/to/stuff', handler=StuffHandler, name='stuff.page'),
    Route('/path/to/more/stuff', handler= MoreStuffHandler, name='more.stuff.page')
))

Если вы решите пойти по этому маршруту, вы, очевидно, можете улучшить его добыть более гибким с другими типами объектов BaseRoute.

0 голосов
/ 12 января 2012

Я не знаком с webapp2, но если первый параметр является регулярным выражением, попробуйте:

/feed(/)?
...