FlaskによるWebアプリ開発⑤~url_forでの動的URLの作成

前回までのシリーズ記事

今回は少し高度なURLルーティング、つまり変数を使った動的なURLの作成方法について解説していきます。

ルーティングとは何か?

Flaskの使い方を色々書いていて今さらにはなりますが、改めてルーティングについて解説するとWebアプリケーションにおけるルーティングとは、URLと内部処理を紐づけすることです

flaskアプリケーションは、関数とURLを紐付けることで、ユーザからアクセスできるようになっています。flaskのルーティングは、.route() で定義されます。これまでなんとなくコピペしていたであろう@app.route()はルーティングを定義しています。

from flask import Flask
app = Flask(__name__)

# http://xxx 以降のURLパスを '/' と指定
@app.route('/') 
def index():
    return 'hello world!!'

上記の例では、 http://xxx/ と index() を紐付けています。http://xxx/ にアクセスすると、「HelloWorld!!」とだけ書かれた質素なページが表示されます。これがもっともシンプルなルーティングです。

静的ファイルのルーティング

webサイトに必要なのはテキストだけではありません。現在のWebサイトのようなオシャレなものを作る場合はタグの装飾を凝ったり画像や動きを付ける必要があります。

なので、もし個人のお遊びではなく、実務などでまともなWebサイトを作ろうとなるとhtml以外に、画像ファイルや、htmlをオシャレにできる「css」、htmlに動きを付ける「Javascript」を扱う必要があります。

CSSやJavaScript、画像といった静的ファイルのルーティングは自動でされます。デフォルトでは、 http://xxx/static が static ディレクトリに対応しています。

htmlを保管している「templates」と同じように、Flaskのアプリケーションファイル内に 「static」 という名前のディレクトリを作成すると自動的にルーティングされます。

前述したような app.route() による定義は必要ありません。フォルダのディレクトリ構成は↓のようなイメージになっています。

<FLASKアプリケーションの典型的なディレクトリ構成>
Flask app
└──app.py
│
└──templates
│   └──index.html
│
└── static
    │
    ├── css
    │   └── test.css
    ├── js
    │   └── test.js
    └──img
        └──test.png

static以下のディレクトリは、ディレクトリ名がパスとしてルーティングされます。上記構成の場合、以下のURLが有効です。

http://xxx/static/img/test.png
http://xxx/static/css/test.css
http://xxx/static/js/test.js

httpメソッドまたはif文での条件分岐ルーティング

app.route()は、引数のmethods=の部分にHTTPのメソッド名のリストを渡してやることで、そのURLが受け入れるHTTPメソッドを指定できます。

何も指定しない場合のデフォルトはmethods=['GET', 'POST']で両方とも受け付けます。

例えばユーザが入力フォームに書いた内容を送信する処理などは、methods=['POST']にすることで、post以外のメソッドを使ったアクセスはじくことができ、セキュリティ対策になります。またメソッドに応じて条件分岐させることも可能です。

@app.route('/', methods=['GET', 'POST'])
def edit():
    # 共通の処理
    if request.method == 'get':
    # GET時の処理
    else:
    # POST時の処理
    # 共通の処理

HTTPメソッドの指定を変えることで、同じURLでも異なる関数へとルーティングできます。

 @app.route('/edit', methods=['GET'])
def get_edit():
    # GET時の処理

@app.route('/edit', methods=['POST'])
def post_edit():
    # POST時の処理

methods に値を指定することで、HTTPメソッドを指定できます。例では、GETとPOSTのリクエストをルーティングしています。

処理の内容にもよりますが、GETとPOSTで異なる処理をすることがほとんどであり、ifで分岐させるよりも、関数を呼び出す時点で分岐しておいた方がコードが見やすくなるので個人的にはそうやって書くことが多いです。

HTTPメソッドごとに関数を定義する場合は、関数名をget_〇〇、post_〇〇のようにしておくとわかりやすいです。

まあこのcssや条件分岐辺りはコードを見ればなんとなくで理解できるので、今まであまり触れていませんでしたが、Webアプリケーションを構築する上で少し難しいのが「変数による動的なルーティング」をするケースです。

「変数による動的URLなルーティング」の顕著な例としては、ログイン制のサイトがあります。適当なサイトにブラウザからログインして、ブラウザの上部を見てもらえれば分かりますが、ユーザー名ごとに自動でURLが作成され、会員ごとに別々のページが表示されています。

この「変数による動的URLルーティング」は僕がflaskを勉強した時にハマったところなので、今回ここで1つ記事にして解説しようと思った次第です。

スポンサーリンク

変数による動的なURLルーティング

たとえば、会員登録して使うサイトなどではUser ID=1のデータをリクエストと一緒に送信したいという場合があります。その場合、値をURLの一部として渡す、もしくは、クエリとして渡すのが一般的です。

<app.py>

from flask import Flask, render_template, url_for, redirect
app = Flask(__name__)

# 社員情報を表示する画面
@app.route("/members")
def user_url():
    lists = [[1,'太郎'], [2,'次郎'], [3,'三郎']]
    return render_template("member.html", lists=lists)


# 社員の詳細情報を表示する画面
@app.route("/member_detail/<int:id_>/<name>")
def detail(id_,name):
    lists = [['太郎',24,'サッカー'], ['次郎',45,'野球'], ['三郎',67,'バスケ']]
    index = id_-1
    data = lists[index]
    return render_template("detail.html", data=data, name=name)


# トップ画面にリダイレクト
@app.route('/redirects')
def redirects():
    return redirect(url_for('index'))


app.run(debug=True)
<index.html>
<html>
<h2>Flaskでurlforでのルーティングを勉強するサンプルアプリ</h2>
<p>
・<a href='/members'>社員情報一覧</a>
</html>

<menber.html>

​<!DOCTYPE html>
<html lang="ja">
<head>
<body>
<p></p>
<table>
    <tr>
        <th>社員ID</th>
        <th>社員名</th>
    </tr>
    <tbody>
    {% block body %}
    {% for d in lists %}

    <tr>
    <td>{{ d[0] }}</td>
    <td>{{ d[1] }}</td>
    <td>
    <a href="{{ url_for('detail',id_=d[0],name=d[1]) }}">詳細</a>
    </td>
    </tr>
   
    {% endfor %}
    {% endblock %}
    </tbody>
</table>
<p></p>
<a href='/redirects'>トップ画面にリダイレクト</a>
</body>
</html>

<detail.html>

<html>
<p></p>
<h3>{{ name }}の社員情報です。</h3>
<p></p>
<table>
  <tr>
      <th>年齢</th>
      <th>趣味</th>
  </tr>
  <tbody>
  <tr>
      <td>{{ data[1] }}歳</td>
      <td>{{ data[2] }}</td>
  </tr>
  </tbody>
</table>
<p></p>
<a href='/redirects'>トップ画面にリダイレクト</a>
</html>

前者のように http://xxx/edit/1 のようにデータをurlに渡したいという場合は、変数付きのルーティングを用います。flaskではURLの後にカッコ有りの記述を入れることで、URLと一緒についてきたものを拾えます。

@app.route("/member_detail/<int:id>/<name>/")の部分ではidとnameを拾っています。int:と付け足すことでidの中身はint型以外受け付けないと指定しています。

データ型は特に指定されていない場合、string(文字型)として扱われます。converterに指定した型と異なる型のデータがURLとして渡された場合、 404 NotFound を返します。

※デコレーターのURL型の説明

・string (デフォルト) /(半角スラッシュ)以外の全ての文字を受け付けます。
・int 正の整数を受け付けます。
・float 正の実数を整数または、小数を受け付けます。
・path スラッシュを含む全ての文字を受け付けます。
・uuid UUID文字列を受け付けます。

そしてhtml上に既に別のルーティングで渡されている情報を、別のURLに移動する際にくっつけておきたい場合は「url_for」を用います。url_forの引数の指定方法はurl_for('送信先の関数名',送信するデータ)です。

今回は "{{ url_for('detail',id_=d[0],name=d[1]) }}" で、送信先の関数としてdetail()を指定しているため、それと紐づいている@app.route("/member_detail//")にアクセスするURLが生成されます。

今回の動的URLには変数部分にid_とnameが設定されているため、キーワード引数としてidとnameに送るデータを指定します。

今回送信されているのはd[0]とd[1]の中身です。そして、送信先の detail() 関数の引数に id_ と name が指定してあるので、送ったデータをそのまま使うことができ、それを利用して対応したユーザーの年齢と趣味の情報を、 detail.html に渡しているという流れになります。

また、変数にはデフォルト値を設定できます。ひとつの関数に対して、複数のURLを紐づけることもできます。この2つを組み合わせると、以下のようなルーティングも可能です。

@app.route('/list')
@app.route('/list/<int:page>')
def get_list(page=1):
    # <int:page> が未指定の場合、page=1が設定される

リダイレクト処理

ログインサイトなんかを作成する場合、ログインが完了してからトップページにリダイレクトするような処理が行われることがあります。これをFlask上で実現するためにはredirectとurlforを使用します。

# トップ画面にリダイレクト
@app.route('/redirects')
def redirects():
    return redirect(url_for('index'))

ここで注意したいのはあくまで、ルート(/とか/members)ではなく、ルートに紐づいている関数名をurl_forの引数に指定する点です。

終わり

以上がFlaskにおけるurl_forを使用した動的なURLの作成とリダイレクト処理の実装方法です。動的なURLはログイン認証サイトなんかを作る際には欠かせないのでぜひ使えるようにしておきましょう。

動くサンプルコードを私のGithubにアップロードしているので、そちらをダウンロードするなりして実際に動かしてもらえるとより理解が深まるかと思います。

次の記事:FlaskによるWebアプリ開発⑥~ファイルダウンロードを実装する

関連記事:【Python】Flask+SQLAlchemyを使って、「ひとこと掲示板」を作る

関連記事:【Python】Flask+MatplotlibでWebアプリにプロットしたグラフを表示する

プログラミングの独学はとても難しい


プログラミングは小学校の義務教育にも導入され始めており、これから社会人として生きていく上でプログラミングはもはや出来て当たり前、出来なれば論外というエクセルレベルの必須スキルになりつつあります。そしてそういう話を聞いて参考書なりを購入して独学でプログラミング勉強しようと思っている人も少なくないでしょう。しかしプログラミングを独学で勉強し始めようと思うものの



・「分からない箇所で詰まって挫折してしまった」

・「勉強する時間が足りない」

・「ネットの記事だと情報が断片的でよくわからない」

・「コードのエラーの原因が分からない」



という壁にぶち当たって、プログラミングの勉強を止めてしまう方が少なくありません。独学でプログラミングを勉強してる時間のほとんどはつまづいている時間です。実際僕も最初のころ独学でプログラミングを勉強していた頃はエラーの原因が分からず丸1日を不意にしてしまった・・・そんな苦い経験がありました。それで僕は一度はプログラミングの学習を諦めてしまいましたが、就活で現実を知る中で



「プログラミングを勉強して、いずれフリーランスとして自由な生き方がしたい」

「エンジニアとして若いうちから高収入を得たい」



という強い気持ちから一念発起して「侍エンジニアのwebサービスコース」に申し込み、プロのエンジニアの方に対面でマンツーマンでPythonによるWebサービス作り方とWeb技術の基本を教えてもらい、ようやくプログラミングが理解でき、今ではエンジニアとしてそこそこの暮らしができるようになりました。





侍エンジニアでは、とりあえずプログラミングやインターネットの基本を知っておきたい人から、HTML・cssなどでWebサイトやWebアプリを作ってみたい人やPythonを勉強してデータサイエンティストやAIエンジニアになりたい人まで幅広いニーズに応えた様々なコースが用意されています。



IT業界と言ってもエンジニアの仕事はプログラミング言語次第でサーバーから機械学習・ディープラーニングまで多種多様ですし、侍エンジニアの無料レッスン(カウンセリング)を受けてみて、自分のやりたいITの仕事は何なのか?を見つけるのがエンジニアへの第一歩になります。ちなみに今侍エンジニアの無料レッスンを受けると1000円分のAmazonギフト券がもらえるので、試しに受けてみるだけもお得です。


自分は半端に独学やオンラインスクールで勉強して金と時間を無駄にするくらいなら、リアルのプログラミングスクールに通ってしっかりプログラミングを勉強した方がいいと思います。ちなみに今、侍エンジニアに申し込むと、25歳以下の学生の方であれば、受講料が20%OFFになるので超お得です。


そして、プログラミングは大勢で授業を受けたり漫然とオンライン学習をするよりも自分が分からない箇所をピンポイントでプロの講師に直接質問して、ちゃんと納得するというスタイルの方がお金は確かに少し掛かりますが、独学で学ぶよりも絶対にモノになります。


シェアする

  • このエントリーをはてなブックマークに追加

フォローする

   侍エンジニア塾       
侍エンジニアの無料体験レッスンを予約する -->