IT業務効率化

Pythonのreponderでhttpリクエストのパタメータを取得する。

はじめに余談

先日投稿しました、はじめてのresponder1。webページを表示させてみる。の続きです。

そもそもどうしてwebページにこだわるかというと、誰にでもプログラミングを楽しんでもらいたいからです。最近事業部側のプログラミング経験0の友達が、プログラミングを教えて欲しいといってきました。けれども

じゃあpythonインストールしてみて!何かわからないことあればなんでも手伝うから!
お、おう・・・

となるのです。急に熱量がどこかにいってしまうのです。

どれだけ便利なコードを書いても、python 〇〇.pyと打つ必要があると、これだけで初心者の人はハードルを感じてしまうようです。僕にプログラミングを教えてくれといってきた友達は、エクセルの細かい手作業を自動化したいと言っていました。まさにそんなものはpythonでサクッとできます。けれども、python 〇〇.pyまでの道のりがわかりづらいのです。これはとてももったいないことだと思います。

そんな人のためにresponderで画面をつくるぞ!!(webページ作るのも初めてですが)

少々長かったですが余談でした。それでは本題に入っていきます。

結論

req.media()で取得できます。

下の2つのコードは、リクエストパラメータを取得するテストとして最小構成になると思っているコードの例です。

HTML

<!DOCTYPE>
<html lang="ja">
    <head>
        <title>hirayukiのhello world</title>
    </head>
    <body>
        <p>Hello, {{name}}!</p>
        <form action="/incoming" method="post">
            <p>
                名前:<input type="text" name="name" size="40">
            </p>
            <p>
                <input type="submit" value="送信">
            </p>
        </form>
    </body>
</html>

main.py

import responder
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):
    @api.background.task
    data = await req.media()
    print(data)

api.run(port=3000)

まずはHTMLにformを作る

今回は文字列と日付をサーバ側のPythonに渡してあげたいので、そのformを作ろうと思います。

HTMLを以下のように用意します。

<!DOCTYPE>
<html lang="ja">
    <head>
        <title>hirayukiのhello world</title>
    </head>
    <body>
        <p>Hello, {{name}}!</p>
        <form method="post">
            <p>
                名前:<input type="text" name="name" size="40">
            </p>
            <p>
                <input type="submit" value="送信">
            </p>
        </form>
    </body>
</html>

これで無事に入力フォームは完成しました。

Python側でリクエストパラメータを取得する

公式ドキュメントにしたがって進めいていきます。早速何書いているのかわかりませんが、とりあえずやってみましょう。

先週のコードに引き続き追記する形で書いていきます。quick startの内容をそのままコピーすると、pythonファイルは以下のようになりました。

import responder
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):
    @api.background.task
    def process_data(data):
        """Just sleeps for three seconds, as a demo."""
        time.sleep(3)


    # Parse the incoming data as form-encoded.
    # Note: 'json' and 'yaml' formats are also automatically supported.
    data = await req.media()

    # Process the data (in the background).
    process_data(data)
    
    print(data)


api.run(port=3000)

2行目のimport timeはデモとして使うのだと思います。実質不要なのですが、一旦入れてみて試そうと思います。responderの特徴として非同期処理が書けるそうなので、そのデモ用かと思われます。(非同期処理はざっくりいうと、他の作業が終わりを待たずに進める処理です。)14行目@api.background.taskはまさにそれだと思います。

13行目asyncは非同期処理である事を明示しています。22行目awaitはその処理が終わるまではそこで停止するという意味です。まるでjavascriptのような書き方ですね。Pythonでは初めてこの書き方を見ました。

最後に送信したいデータがちゃんと取得できているか見たいのでprint文を入れています。

では早速!webページからデータを送信してみたいと思います!

「送信」!Pythonを実行したコマンドラインを確認してみます。

(responder) yuki-PC:test_responder yuki$ python main.py 
INFO: Started server process [45101]
INFO: Waiting for application startup.
INFO: Uvicorn running on http://127.0.0.1:3000 (Press CTRL+C to quit)
INFO: ('127.0.0.1', 62004) - "GET /hello HTTP/1.1" 404
INFO: ('127.0.0.1', 62006) - "GET /hello.html HTTP/1.1" 200
INFO: ('127.0.0.1', 62089) - "GET /hello.html HTTP/1.1" 200
INFO: ('127.0.0.1', 62134) - "GET /hello.html HTTP/1.1" 200
INFO: ('127.0.0.1', 62319) - "POST /hello.html HTTP/1.1" 200

お、POST送信された記録はありますね。なのにリクエストパラメータとして渡したつもりのhirayukiはどこにもないです。

ここで結構詰まりました。

print文が失敗しているのか?一体どうやったら取得したデータを確認できるんだ!?

はあー、もうダメだと思ったとき、

ん・・・このincomingってなんだ・・・?

よくよくhtmlのformについて勉強すると、タグの中にactionという属性を用いて、送信先を指定するそうなのです。何も書いていないと言うことで、python側のコードでいうとhello_htmlに送られていました。

formタグのactionのURLをpythonと合わせる

formタグの中にaction属性を書き込みました。

<form action="/incoming" method="post">

これでどうだ!

つ、ついに取れました。

おわりに

前回の記事のサムネで概略図まで書いておいてお恥ずかしい。

responderでリクエストパラメータを取得するためには

  • @api.route(“”)の引数で、URLの指定先の名前を明示しすること。
  • HTMLのformのactionでそのURLを指定すること。

が必要です。

これでPython側にブラウザから値を渡してやることができました!!

次回は受け取った値を元に、結果を返す部分を作りたいと思います。

Pythonのresponder入門|webページを表示させてみる。はじめに この記事ではresponderでwebアプリをhello worldしてみたいと思います。 目標は管理画面の作成です。...
ABOUT ME
hirayuki
今年で社会人3年目になります。 日々体当たりで仕事を覚えています。 テーマはIT・教育です。 少しでも技術に親しんでもらえるよう、noteで4コマ漫画も書いています。 https://note.mu/hirayuki