2011-02-04 24 views
1

私はこのような何かをしたいと思います:python appengineでベースハンドラーからハンドラーを呼び出す方法はありますか?

class Basehandler(webapp.RequestHandler): 

    def __init__(self): 
    if checkforspecialcase: #check something that always needs to be handled 
     return SpecialCaseHandler.get() 

class NormalHandler(Basehandler): 

    def get(self): 
    print 'hello world' 
    return 

class SpecialCaseHandler(Basehandler): 

    def get(self): 
    print 'hello special world' 
    return 

アイデアは、特定のケースが満たされた場合に関係なく、最初に呼ばれているものハンドラ、我々は基本的に別のハンドラに切り替えていないということです。

私はかなりPythonに新しいので、私がしようとしていることが可能かどうかは分かりません。またはこれが最良のアプローチであるかどうか。私が実際にやっていることは、登録プロセスを開始しても完了していない場合は誰でもプロファイルページを表示することです。したがって、 "checkforspecialcase"はセッションを見て、不完全な情報をチェックします。

答えて

3

Template Method patternを使用し、DRYものを維持するには

class BaseHandler(webapp.RequestHandler): 
    def DoGet(self, *args): 
     ''' defined in derived classes, actual per-handler get() logic''' 
     pass 

    def get(self, *args): 
     # don't get caught in endless redirects! 
     if specialCase and not self.request.path.startswith('/special'): 
      self.redirect('/special') 
     else: 
      self.DoGet(*args) 

class NormalHandler(BaseHandler): 
    def DoGet(self, *args): 
     # normal stuff 

class SpecialHandler(BaseHandler): 
    def DoGet(self, *args): 
     # SPECIAL stuff 
3

WSGIApplicationは、URLに基​​づいて着信要求をルーティングします。 checkforspecialcaseが経過すると例えば、

application = webapp.WSGIApplication(
       [('/special-case', SpecialCaseHandler)]) 

は、あなたがself.redirect('/special-case')を使用することができます。

+0

私が試した最初のことでしたが、行っていません。上記の条件の後にself.redirect( '/ special-case')を置くと、次のエラーが発生します。 "AttributeError: 'NormalHandler'オブジェクトに 'request'属性がありません。 get()メソッドまたはpost()メソッド内では使用できますが、初期化メソッドでは使用できません。 –

+0

はい、そうです。 'get'メソッドでその条件を使うのはなぜですか?なぜ私たちは '__init__'を必要としますか? – dheerosaur

+0

この条件をすべてのページに適用したいので、ベースハンドラークラスで一度行ってください。そして、ベースハンドラーを拡張するクラスのget/postメソッドは、ベースハンドラーのget/postメソッドを上書きすると信じています。だから、これをget/postメソッドに入れるには、get/postメソッドごとに記述する必要があります。ただ乾くようにしよう。 –

0

あなたのベースハンドラは、特別なケースをチェックし、self.view()をリダイレクトするか呼び出すget()を実装するだけで、各ハンドラはview()(またはそれを呼びたいもの) get()よりも。

私は私のハンドラのそれぞれのクラスを書いて、またはそう顕著継承を使用してに本当にないんだけど、私はこのような転がりデコレータをお勧めします:

routes = [] 

def get (route): 
    def makeHandler (handle, *args, **kwargs): 
     class Handler (webapp.RequestHandler): 
      def get (self, *args, **kwargs): 
       shouldRedirectToCompleteProfile = # do your test 
       if shouldRedirectToCompleteProfile: 
        self.redirect('/special-case') 
       else: 
        handle(self, *args, **kwargs) 
     routes.append((route, Handler)) 
     return Handler 
    return makeHandler 

def post (route): 
    def makeHandler (handle, *args, **kwargs): 
     class Handler (webapp.RequestHandler): 
      def post (self, *args, **kwargs): 
       handle(self, *args, **kwargs) 
     routes.append((route, Handler)) 
     return Handler 
    return makeHandler 

@get('/') 
def home (ctx): 
    # <...> 

@get('/whatever/(.*)/(.*)') 
def whatever (ctx, whatever0, whatever1): 
    # <...> 

@post('/submit') 
def submit (ctx): 
    # <...> 

application = webapp.WSGIApplication(routes) 
+0

@bgporterのやり方の唯一の問題は、100番目のハンドラをコーディングしているときにDoGet()ではなくget()を誤って実装すると、面倒なバグが発生することです。リダイレクトをチェックする機能テストを100回作成するか、get()オーバーライドを探す静的解析ユニットテストを作成することで、安心して自分を設定できます。あるいは、私が示唆しているようにデコレータを使用している場合は、そのようなバグを導入することは不可能であるため、テストは必要ありません。 – dfichter

関連する問題