IT業務効率化

Python responderを使ってリクエストに応じたwebページを返す1

前回までは

htmlのformに入力した値をサーバサイドのPythonで取得することができました。ソースコードは今の所こんな感じです。

import time

api = responder.API()


@api.route("/hello.html")
def hello_html(req, resp):
    my_name = "hirayuki"
    resp.html = api.template('index.html', name=my_name)

@api.route("/incoming")
async def receive_incoming(req, resp):
    data = await req.media()
    print(data)

api.run(port=3000)

ここからスタートしようと思います。

その前に、asyncとawaitは取れるのか?

まずはPythonコードを必要最低限の構成にしようと思い、responder Quick startのコードを丸々コピーしたものから無駄なものを省こうと思いました。そのなかでもfunctionを定義する前につけているasyncとその関数内に書かれているawaitを外そうと思いました。これからやりたい処理はPython側で非同期でやる必要はないので、外しても実装上は問題ないかなと思いました。しかし、これでwebページを立ち上げるとエラーが発生してしまいました。

<coroutine object Request.media at 0x10a21a570>
/anaconda3/envs/py36/lib/python3.6/site-packages/uvicorn/main.py:303: RuntimeWarning: coroutine 'Request.media' was never awaited
  loop.run_until_complete(self.serve(sockets=sockets))

RuntimeWarning: coroutine だそうです。

色々と調べてみたのですが、とりあえずわかったことは

  • asyncはresponder固有のものではなく、asyncioなど他のライブラリにも存在しおり、非同期処理を明示するために書く
  • リクエストパラメータを取得する時には、awaitは必須
  • asyncは奥が深そう・・・

とうことです。なのでasyncはまた別の機会にブログにまとめようと思います。

今回は一旦やりたい事をごり押しして、手を動かして覚えようと思います。

今日の目標:データを検索して管理画面に表示する

今回やりたいこのイメージとしてはこんな感じです。

顧客氏名・日付などを入力。それを元にサーバへのアクセス履歴などをブラウザ上に返す事です。

POSTする先の関数の中でtemplateを返してみる

@api.route("/hello.html")
def hello_html(req, resp):
    my_name = "hirayuki"
    resp.html = api.template('index.html', name=my_name)

と書いておき、http://localhost:<port>/hello.html にアクセスすると、templatesディレクトリにあるindex.htmlファイルをブラウザに返してくれるところまでが前回でした。なのでこの

resp.html = api.template(‘index.html’, name=my_name)

をデータをPOSTしている先の関数である、receive_incomingにも書いてあげれば、うまくいくのではないかという作戦です。まずはやってみます。

@api.route("/incoming")
async def receive_incoming(req, resp):
    data = await req.media()
    resp.html = api.template('index.html', name=data)
    print(data)

今回はnameの表示のところに、受け取ったデータを入れて返そうと思います。準備はできました。

これでブラウザが更新され、Hello, HIRATESTとなれば成功です。どうでしょうか?

えい!

お!{‘name’: [‘HIRATEST’]}で返ってきましたね。辞書型(連想配列)で返ってきているのは気づきませんでしたが、あとで修正します。そっちよりも気になっているのが・・・URLです。incoming・・・?

私もまだ理解の途中ですが、http://localhost:3000/incoming というURLはあくまでPOSTでデータを送る先であって、ブラウザにURLとして表示されるのは違うような気がするのです。ブックマークもできませんし。

次回はこのURLが遷移しないようにするための方法を模索します。

githubのリンク

Python responderを使ってリクエストに応じたwebページを返す2はじめに 私のブログ全体に言えることなのですが、苦労した箇所や混乱した箇所は抜け漏れなく書いております。そのため体系的にまとめられた記...
ABOUT ME
hirayuki
今年で社会人3年目になります。 日々体当たりで仕事を覚えています。 テーマはIT・教育です。 少しでも技術に親しんでもらえるよう、noteで4コマ漫画も書いています。 https://note.mu/hirayuki