4

我正在学习具有强大路由机制的webapp2框架。

我的应用程序应该接受这样的 URI:

/poll/abc-123
/poll/abc-123/
/poll/abc-123/vote/       # post new vote
/poll/abc-123/vote/456    # view/update a vote

民意调查可以选择组织成类别,因此以上所有内容也应该像这样工作:

/mycategory/poll/abc-123
/mycategory/poll/abc-123/
/mycategory/poll/abc-123/vote/
/mycategory/poll/abc-123/vote/456

我的错误配置:

app = webapp2.WSGIApplication([
    webapp2.Route('/<category>/poll/<poll_id><:/?>', PollHandler),
    webapp2.Route('/<category>/poll/<poll_id>/vote/<vote_id>', VoteHandler),
], debug=True)

问题:如何修复我的配置?

如果可能的话,它应该针对 GAE CPU 时间/托管费用进行优化。例如,如果我为每个条目添加两行可能会更快:一行有类别,另一行没有类别...

4

2 回答 2

7

webapp2 具有重用公共前缀的机制,但在这种情况下它们会有所不同,因此您无法避免重复这些路由,如下所示:

app = webapp2.WSGIApplication([
    webapp2.Route('/poll/<poll_id><:/?>', PollHandler),
    webapp2.Route('/poll/<poll_id>/vote/<vote_id>', VoteHandler),
    webapp2.Route('/<category>/poll/<poll_id><:/?>', PollHandler),
    webapp2.Route('/<category>/poll/<poll_id>/vote/<vote_id>', VoteHandler),
], debug=True)

您不必担心添加许多路线。它们的建造和匹配真的很便宜。除非你有成千上万,否则减少路线的数量并不重要。

一个小提示:第一条路线接受一个可选的结束斜线。您可以改为使用RedirectRoute来仅接受一个并在访问另一个时重定向,使用选项strict_slash=True。这没有很好的记录,但已经存在了一段时间。请参阅文档字符串中的说明

于 2011-08-13T12:20:09.687 回答
1

我将在@moraes 之上添加我的解决方案作为补充答案。
所以其他有以下问题的人可以获得更完整的答案。

  1. 斜线问题
  2. 可选参数问题

此外,我想出了如何在一个正则表达式中同时/entity/create路由/entity/edit/{id}
以下是我支持以下 url 模式的路线。

  1. /
  2. /myentities
  3. /myentities/
  4. /myentities/创建
  5. /myentities/创建/
  6. /myentities/edit/{entity_id}
SITE_URLS = [
    webapp2.Route(r'/', handler=HomePageHandler, name='route-home'),

    webapp2.Route(r'/myentities/<:(create/?)|edit/><entity_id:(\d*)>',
        handler=MyEntityHandler,
        name='route-entity-create-or-edit'),

    webapp2.SimpleRoute(r'/myentities/?',
        handler=MyEntityListHandler,
        name='route-entity-list'),
]

app = webapp2.WSGIApplication(SITE_URLS, debug=True)

下面是我BaseHandler所有的处理程序都继承自。

class BaseHandler(webapp2.RequestHandler):
    @webapp2.cached_property
    def jinja2(self):
        # Sets the defaulte templates folder to the './app/templates' instead of 'templates'
        jinja2.default_config['template_path'] = s.path.join(
            os.path.dirname(__file__),
            'app',
            'templates'
        )

        # Returns a Jinja2 renderer cached in the app registry.
        return jinja2.get_jinja2(app=self.app)

    def render_response(self, _template, **context):
        # Renders a template and writes the result to the response.
        rv = self.jinja2.render_template(_template, **context)
        self.response.write(rv)

下面是我的MyEntityHandlerpython 类,带有Google App Engine Datastore APIget()的方法签名。

class MyEntityHandler(BaseHandler):
    def get(self, entity_id, **kwargs):
        if entity_id:
            entity = MyEntity.get_by_id(int(entity_id))
            template_values = {
                'field1': entity.field1,
                'field2': entity.field2
            }
        else:
            template_values = {
                'field1': '',
                'field2': ''
            }
    self.render_response('my_entity_create_edit_view_.html', **template_values)



    def post(self, entity_id, **kwargs):
        # Code to save to datastore. I am lazy to write this code.

        self.redirect('/myentities')
于 2012-12-18T21:54:50.263 回答