最初からのGoogle AppEngine:コントローラー

私たちはジェット列車の速度で前進しており、ハラの人々が記事の最初2番目の部分を読んで理解している間に、マシンガンの速度の続編を書いています。 今回は、すべてのWebアプリケーションの中心です。



コントローラー



少し前に、 app.yaml



いくつかのURLを既に定義しました。アプリケーションをそれらに正しく「応答」させる方法を見つけ出す時です。 マッピングは次のようになります。



 #$ Id:app.yaml 4 2010-01-25 12:14:48Z sigizmund $

アプリケーション:helloworld
バージョン:1
ランタイム:python
 api_version:1

ハンドラー:
 -url:/(統計|ログイン)
  スクリプト:main.py
  ログイン:必須

 -url :. *
  スクリプト:main.py




ご覧のとおり、3種類のURLが定義されています- /stats



/login



および「その他」。 通常の3つすべては同じmain.py



スクリプトで処理されますが、設定は異なります- /stats



および/login



はアクティブなユーザーセッションを必要としますが、その他の場合はこれは必要ありません。 main.py



スクリプトの内容を見てみましょう。



 #!/ usr / bin / env python

 '' '
 $ Id:main.py 4 2010-01-25 12:14:48Z sigizmund $
 '' '

インポートコントローラー

 google.appengine.extからwebappをインポート
 google.appengine.ext.webapp import utilから
 google.appengine.apiインポートユーザーから

 def main():
   application = webapp.WSGIApplication([( '/'、controller.DefaultRequestHandler)、 
                                 ( '/ stats'、controller.StatsRequestController)、
                                 ( '/ login'、controller.LoginController)]、
                                        debug = True)
   util.run_wsgi_app(アプリケーション)


 __name__ == '__main__'の場合:
  メイン()




かなり簡潔です。 つまり、非常に簡潔ですが、同時に非常に重要です。 controllers



のコンテンツをインポートし、リクエストURLと対応するハンドラーに一致するwebapp.WSGIApplication



インスタンスを作成するwebapp.WSGIApplication



です。 通常、これらのハンドラーは、実際のアプリケーションの動作を決定する実際のコードからサービスコードを分離するために、個別のパッケージに入れると便利です。 これらのハンドラーを順番に検討してください。



DefaultRequestHandler-デフォルトハンドラー



上記のコードからわかるように、このハンドラーは、アプリケーションの「メインページ」、つまり「/」に到達したすべてのリクエストに使用されます。 そのコードは次のとおりです。



クラスDefaultRequestHandler(webapp.RequestHandler): 
     '' '
    デフォルトのリクエストを処理-ユーザーがログインしているかどうかを確認します。 もしそうなら-に関する情報を保存します
    データベースへの彼の訪問。
     '' '

     def get(self):
        ユーザー= users.get_current_user()

        ページ=なし
        ユーザーでない場合:
             page = view.StartPage(self.request)
        その他:
             page = view.WelcomePage(self.request)

         page.render(self.response.out)




基本的に、このコードは、ページ自体のコンテンツを生成せず、いくつかの補助クラスを使用することを除いて、 最初の部分の MainHandler



コードとMainHandler



です。 この段階では、彼らが何をしているのかを考慮しません-私たちにとっては、彼らが私たちの要件を満たすHTMLを生成することを知るだけで十分です-つまり、これはログインしていないユーザーにログインを提供し、それに成功した人を歓迎します。



ログインハンドラー-2ページ間



アプリケーションの構造を示す画像を思い出させてください:



ゲーハブル



/login



ページの説明からわかるように、ユーザーは自動的にリダイレクトされ、ページ/



も自動的にリダイレクトされます。 このページで何が起こっていますか? これを行うには、2つのクラスを一度に検討する必要があります。



クラスLoggedInRequestHandler(webapp.RequestHandler):
     def currentVisitor(自己):
        ユーザー= users.get_current_user()

         #/ loginおよび/ statsが指定するように、ユーザーをチェックするべきではありません 
         #ログイン:app.yamlで必要

         q = model.Visitor.all()
         q.filter(「ユーザー=」、ユーザー)

         qr = q.fetch(2)

         len(qr)== 0の場合:
             u = model.Visitor()
         elif len(qr)> 1:
             #ここで何かがひどく間違っている、それは起こるべきではない
             #しかし、それでもまだ
             logging.error(「データストアでユーザー%sを複製しています」%user.nickname())
            例外を発生させます(「データストアでuser%を複製しています」%user.nickname())
        その他:
             u = qr [0]

         self.currentVisitor = u
        あなたを返す




これは最良のアーキテクチャソリューションではないかもしれませんが、説明のために、クラスを宣言し、 webapp.RequestHandler



から継承しwebapp.RequestHandler



。 ご覧のとおり、説明したクラスはget



メソッドを定義していません。つまり、独立した開発者としては、ほとんど役に立たないでしょう。 彼がしているのは、データストアから取得するか、新しいVisitor



インスタンスを作成して返すcurrentVisitor()



メソッドを提供することだけです。 このコードをさらに詳しく検討してください。



説明したアプローチでは、このタイプの「すべて」のオブジェクトで始まるDatastore Queryを使用し、その後filter()



およびancestor()



呼び出して最終データセットを徐々に「洗練」します。 上記の例は非常に単純ですが、データストアから必要なレコードを抽出するために必要なほとんどすべてを示しています。 もちろん、実際のアプリケーションでは、このクエリはおそらくはるかに複雑になります。



このような便利なクラスができたので、ハンドラーを簡単に記述できます。



クラスLoginController(LoggedInRequestHandler): 
     '' '
    ログインイベントを処理するためだけにこのコントローラーを使用します
     '' '
     def get(self):
         u = self.currentVisitor()

         u.hits = u.hits + 1
         u.put()

         self.redirect( '/')


コードからわかるように、ハンドラーは現在のユーザーに関連付けられたVisitorインスタンスを受け取り(作成する可能性があります)、訪問数を1つ増やして、インスタンスを保存します。 その後、ユーザーは苦労せずにメインページにリダイレクトされます。 URL /login



必須ログインが必要である/login



マークされているため、ユーザーを確認する必要がなくなります(つまり、ユーザーが認証なしでログインしようとすると、ログインページに自動的にリダイレクトされます)。



StatsRequestController-リクエストに関する統計



最後のハンドラーのコードは非常に単純です。 それは非常に単純なので、明らかに何か他のものがあるはずであることを示唆しています:



クラスStatsRequestController(LoggedInRequestHandler): 
     def get(self):
         u = self.currentVisitor()
         page = view.StatsPage(self.request、u)

         page.render(self.response.out)


確かに、何か他のものがあります。 これはプレゼンテーションと呼ばれるもので、Djangoテンプレートを使用します。記事の次の部分で説明します;-)



SVNで完全なソースコードを表示できることを思い出してください。質問やコメントをお待ちしています。



PS考えてください、Habrでバックライト付きのソースをアップロードする方法-そうでなければ、すべての写真をアップロードします!



All Articles