2012-07-23 63 views
2

我想通過裝飾它們來定義RequestHandler對象上的路由,而不是在創建應用時提供列表。使用Google應用引擎的webapp2裝飾器路由

我WSGIApplication會被定義如下:

class WSGIApplication(webapp2.WSGIApplication): 
    def __init__(self, *args, **kwargs): 
     super(WSGIApplication, self).__init__(*args, **kwargs) 
     self.router.set_dispatcher(self.__class__.custom_dispatcher) 

    @staticmethod 
    def custom_dispatcher(router, request, response): 
     rv = router.default_dispatcher(request, response) 
     if isinstance(rv, basestring): 
      rv = webapp2.Response(rv) 
     elif isinstance(rv, tuple): 
      rv = webapp2.Response(*rv) 

     return rv 

    def route(self, url, name): 
     def outer_wrapped(cls): 
      logging.info("Adding route %s to class %s with name %s" 
         % (url, cls, name)) 
      self.router.add(RedirectRoute(url, cls, 
              name=name, 
              strict_slash=True)) 
      return cls 
     return outer_wrapped 

package.utils

而且我在package.application

app.yaml中定義我的應用程序有

application: theapplication 
version: 1 
runtime: python27 
api_version: 1 
threadsafe: yes 

handlers: 
- url: .* 
    script: package.main.application 
    secure: always 

package.main是弗洛WS:

from package.application import application 
from package.pages import pages 

package.application如下(與密鑰哈希出):

from package import utils 

conf = {} 
conf['webapp2_extras.sessions'] = {'secret_key': 
    """##############################################"""} 

application = utils.WSGIApplication([], config=conf) 

和這裏有幾個處理程序從package.pages

from package.application import application as app 


@app.route('/conversations', 'view_messages') 
class Messages(BaseHandler): 
    @users.require_login 
    def get(self): 
     conversations = self.current_user.get_user_conversations() 
     return self.render('conversations.slim', conversations=conversations) 


@app.route('/', 'index') 
class Index(BaseHandler): 
    def get(self): 
     return self.render('index.slim') 

索引頁作品好,其他所有404s,日誌簡單地說:

INFO  2012-07-23 14:23:46,258 __init__.py:26] /notifications 
INFO  2012-07-23 14:23:46,272 dev_appserver.py:2952] "GET /notifications HTTP/1.1" 404 - 

我認爲這是由appengine的導入緩存以某種方式導致的,防止裝飾器被運行並添加到應用程序中。

當然,我陷入了陷阱,假設我有任何線索導致問題。我加了進一步的日誌報表輸出路由列表嘗試每次發貨前,我發現,所有路由都在路由器正如人們所預料:

... 
    def custom_dispatcher(router, request, response): 
     logging.info(router.match_routes) 
     logging.info(router.build_routes) 
     rv = router.default_dispatcher(request, response) 
    ... 

具有以下日誌輸出在我的瀏覽器指向/對話:

INFO  2012-08-04 13:16:40,513 utils.py:13] [<Route('/friendship', <class 'package.pages.pages.Friendship'>, name='friendship', defaults={}, build_only=False)>, <Route('/friendship/', <class 'webapp2.RedirectHandler'>, name=None, defaults={'_uri': <bound method RedirectRoute._redirect of <Route('/friendship', <class 'package.pages.pages.Friendship'>, name='friendship', defaults={}, build_only=False)>>, '_name': 'friendship'}, build_only=False)>, <Route('/signup', <class 'package.pages.pages.Signup'>, name='signup', defaults={}, build_only=False)>, <Route('/signup/', <class 'webapp2.RedirectHandler'>, name=None, defaults={'_uri': <bound method RedirectRoute._redirect of <Route('/signup', <class 'package.pages.pages.Signup'>, name='signup', defaults={}, build_only=False)>>, '_name': 'signup'}, build_only=False)>, <Route('/preferences', <class 'package.pages.pages.UserPage'>, name='user_prefs', defaults={}, build_only=False)>, <Route('/preferences/', <class 'webapp2.RedirectHandler'>, name=None, defaults={'_uri': <bound method RedirectRoute._redirect of <Route('/preferences', <class 'package.pages.pages.UserPage'>, name='user_prefs', defaults={}, build_only=False)>>, '_name': 'user_prefs'}, build_only=False)>, <Route('/<username:[a-zA-Z]+>', <class 'package.pages.pages.UserPage'>, name='user_page', defaults={}, build_only=False)>, <Route('/<username:[a-zA-Z]+>/', <class 'webapp2.RedirectHandler'>, name=None, defaults={'_uri': <bound method RedirectRoute._redirect of <Route('/<username:[a-zA-Z]+>', <class 'package.pages.pages.UserPage'>, name='user_page', defaults={}, build_only=False)>>, '_name': 'user_page'}, build_only=False)>, <Route('/message', <class 'package.pages.pages.SendMessagePage'>, name='send_message', defaults={}, build_only=False)>, <Route('/message/', <class 'webapp2.RedirectHandler'>, name=None, defaults={'_uri': <bound method RedirectRoute._redirect of <Route('/message', <class 'package.pages.pages.SendMessagePage'>, name='send_message', defaults={}, build_only=False)>>, '_name': 'send_message'}, build_only=False)>, <Route('/conversations', <class 'package.pages.pages.Messages'>, name='view_messages', defaults={}, build_only=False)>, <Route('/conversations/', <class 'webapp2.RedirectHandler'>, name=None, defaults={'_uri': <bound method RedirectRoute._redirect of <Route('/conversations', <class 'package.pages.pages.Messages'>, name='view_messages', defaults={}, build_only=False)>>, '_name': 'view_messages'}, build_only=False)>, <Route('/conversation/<conversation_id>', <class 'package.pages.pages.ConversationPage'>, name='conversation', defaults={}, build_only=False)>, <Route('/conversation/<conversation_id>/', <class 'webapp2.RedirectHandler'>, name=None, defaults={'_uri': <bound method RedirectRoute._redirect of <Route('/conversation/<conversation_id>', <class 'package.pages.pages.ConversationPage'>, name='conversation', defaults={}, build_only=False)>>, '_name': 'conversation'}, build_only=False)>, <Route('/boards', <class 'package.pages.pages.Boards'>, name='view_boards', defaults={}, build_only=False)>, <Route('/boards/', <class 'webapp2.RedirectHandler'>, name=None, defaults={'_uri': <bound method RedirectRoute._redirect of <Route('/boards', <class 'package.pages.pages.Boards'>, name='view_boards', defaults={}, build_only=False)>>, '_name': 'view_boards'}, build_only=False)>, <Route('/boards/<board>', <class 'package.pages.pages.BoardPage'>, name='view_board', defaults={}, build_only=False)>, <Route('/boards/<board>/', <class 'webapp2.RedirectHandler'>, name=None, defaults={'_uri': <bound method RedirectRoute._redirect of <Route('/boards/<board>', <class 'package.pages.pages.BoardPage'>, name='view_board', defaults={}, build_only=False)>>, '_name': 'view_board'}, build_only=False)>, <Route('/boards/<board>/new_thread', <class 'package.pages.pages.NewThreadPage'>, name='new_thread', defaults={}, build_only=False)>, <Route('/boards/<board>/new_thread/', <class 'webapp2.RedirectHandler'>, name=None, defaults={'_uri': <bound method RedirectRoute._redirect of <Route('/boards/<board>/new_thread', <class 'package.pages.pages.NewThreadPage'>, name='new_thread', defaults={}, build_only=False)>>, '_name': 'new_thread'}, build_only=False)>, <Route('/notifications', <class 'package.pages.pages.Notifications'>, name='notifications', defaults={}, build_only=False)>, <Route('/notifications/', <class 'webapp2.RedirectHandler'>, name=None, defaults={'_uri': <bound method RedirectRoute._redirect of <Route('/notifications', <class 'package.pages.pages.Notifications'>, name='notifications', defaults={}, build_only=False)>>, '_name': 'notifications'}, build_only=False)>, <Route('/img/<blob_key>', <class 'package.pages.pages.DisplayImagePage'>, name='display_image', defaults={}, build_only=False)>, <Route('/img/<blob_key>/', <class 'webapp2.RedirectHandler'>, name=None, defaults={'_uri': <bound method RedirectRoute._redirect of <Route('/img/<blob_key>', <class 'package.pages.pages.DisplayImagePage'>, name='display_image', defaults={}, build_only=False)>>, '_name': 'display_image'}, build_only=False)>, <Route('/', <class 'package.pages.pages.Index'>, name='index', defaults={}, build_only=False)>, <Route('/', <class 'webapp2.RedirectHandler'>, name=None, defaults={'_uri': <bound method RedirectRoute._redirect of <Route('/', <class 'package.pages.pages.Index'>, name='index', defaults={}, build_only=False)>>, '_name': 'index'}, build_only=False)>] 
INFO  2012-08-04 13:16:40,513 utils.py:14] {'index': <Route('/', <class 'package.pages.pages.Index'>, name='index', defaults={}, build_only=False)>, 'view_boards': <Route('/boards', <class 'package.pages.pages.Boards'>, name='view_boards', defaults={}, build_only=False)>, 'notifications': <Route('/notifications', <class 'package.pages.pages.Notifications'>, name='notifications', defaults={}, build_only=False)>, 'friendship': <Route('/friendship', <class 'package.pages.pages.Friendship'>, name='friendship', defaults={}, build_only=False)>, 'signup': <Route('/signup', <class 'package.pages.pages.Signup'>, name='signup', defaults={}, build_only=False)>, 'view_messages': <Route('/conversations', <class 'package.pages.pages.Messages'>, name='view_messages', defaults={}, build_only=False)>, 'conversation': <Route('/conversation/<conversation_id>', <class 'package.pages.pages.ConversationPage'>, name='conversation', defaults={}, build_only=False)>, 'send_message': <Route('/message', <class 'package.pages.pages.SendMessagePage'>, name='send_message', defaults={}, build_only=False)>, 'new_thread': <Route('/boards/<board>/new_thread', <class 'package.pages.pages.NewThreadPage'>, name='new_thread', defaults={}, build_only=False)>, 'view_board': <Route('/boards/<board>', <class 'package.pages.pages.BoardPage'>, name='view_board', defaults={}, build_only=False)>, 'display_image': <Route('/img/<blob_key>', <class 'package.pages.pages.DisplayImagePage'>, name='display_image', defaults={}, build_only=False)>, 'user_prefs': <Route('/preferences', <class 'package.pages.pages.UserPage'>, name='user_prefs', defaults={}, build_only=False)>, 'user_page': <Route('/<username:[a-zA-Z]+>', <class 'package.pages.pages.UserPage'>, name='user_page', defaults={}, build_only=False)>} 
INFO  2012-08-04 13:16:40,515 __init__.py:26] /conversations 
INFO  2012-08-04 13:16:40,533 dev_appserver.py:2952] "GET /conversations HTTP/1.1" 404 - 
INFO  2012-08-04 13:16:40,626 dev_appserver.py:2952] "GET /favicon.ico HTTP/1.1" 200 - 

究竟是什麼我沒有注意到?

+0

我已根據要求更新了帖子。我的印象是,添加主函數只適用於使用cgi的較老的非線程安全運行時。 – KitB 2012-07-23 17:10:18

+0

你是對的。我試過了,它可以同時工作。我認爲問題在於你的裝飾器應該讀取application.route而不是app.route(應用程序沒有在任何地方定義,或者它在packages.pages中?),但是這會引發錯誤。 – 2012-07-23 18:56:53

+0

哦,我正在做'從包裝。應用程序導入應用程序作爲應用程序' – KitB 2012-07-23 23:57:42

回答

0

我有一條覆蓋所有其他路線,但提高他們404(/用戶名導致用戶頁;沒有用戶稱爲「對話」)的路線。我忘記了在切換到裝飾器路由方法時使這條路線具有最低的優先級。

我想通過首先使用相同的路由方法構建一個最小的應用程序來發現它在應用引擎上工作得很好。然後,我在處理程序中捕獲了HTTPNotFound異常,並在發生堆棧跟蹤時發送;這很明顯,它是我的用戶頁面類的get方法中的一條線,故意拋出一個404,然後這些問題相當明顯。