私たちはジェット列車の速度で前進しており、ハラの人々が記事の
最初と
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でバックライト付きのソースをアップロードする方法-そうでなければ、すべての写真をアップロードします!