Python
Flask

PythonのFlaskで学ぶWebアプリケーション制作講座 第3章 〜プログラムの再利用・ルーティング〜

全体の目次はこちら


関数

Pythonも多くの言語のように関数が定義できる。たとえば、二乗をする関数squareを実装してみよう。

#!/usr/bin/python3

# coding: UTF-8

def square(a):
return a**2

print(square(3))

このようにdefを用いることで関数を定義できる。また、引数の型は特に指定する必要がない。末尾に「:」をつけるのを忘れないように。関数のスコープは例にもれずインデントで決まる。

一般に関数定義の文法は

def 関数名(引数1, 引数2, ...):

#処理
return 値

というようになる。


モジュール

ここでは今までは定型文として特に意識して使ってこなかったimportやfromについて解説する。

モジュールとは定義や文が入ったファイルである。したがって、自分で作成することもできるし、特定のディレクトリに配置すればローカル内の任意の場所で使うことができる。

ここでは例えば、myfuncsというモジュールを作ることを考えよう。

#!/usr/bin/python3

# coding: UTF-8

def add(a, b):
return a+b

def subtract(a, b):
return a-b

これをmyfuncs.pyというファイル名で保存してほしい。そうして、同じディレクトリに適当にファイルを作り下記内容で使ってみよう。

#!/usr/bin/python3

# coding: UTF-8

import myfuncs

print(myfuncs.add(6,4))
print(myfuncs.subtract(6,4))

import myfuncs

でmyfuncsを取り込み

モジュール名.関数名

という形でアクセスできる。(ちなみにモジュール名には.pyが含まれないので注意)また、addやsubtract関数が他のものと衝突しないとわかっている場合

#!/usr/bin/python3

# coding: UTF-8

from myfuncs import add, subtract

print(add(6,4))
print(subtract(6,4))

のようにfromをつかうことでアクセスの際にモジュール名を指定せずにアクセスできる。重要なポイントとしてはimport以降のものが名前として取り込まれるということだ。


ルーティング

今までは"/"に対するアクセスのみを扱ってきた。しかし"/main"のように"/"以外のところにアクセスさせたいこともあるだろう。あるいは"/user/taromaru"のようにユーザ固有のページをURLで分類したいようなこともある。それを実現するのがFlaskのルーティング機能だ。

#!/usr/bin/python3

# -*- coding: utf-8 -*-

from flask import Flask
app = Flask(__name__)

@app.route('/')
def index():
return 'Index Page'

@app.route('/hello')
def hello():
return 'Hello World'

if __name__ == "__main__":
app.run(debug=True)

これを実行して「 http://127.0.0.1:5000/ 」、「http://127.0.0.1:5000/hello 」それぞれにアクセスしてほしい。ちゃんと違うページが表示されたかと思う。このように関数定義の前に

@app.route('ルーティングしたいURL')

def 関数名()

としてあげることで、そのURLが指定されたとき、@app.routeの直後にある関数が呼ばれるようになる。ちなみにこの@から始まるものはデコレータとよばれ、関数に作用させることで使うことができる。本講座では詳細には立ち入らないが名前ぐらいは知っておくと良いだろう。

つぎは先ほどだした"/user/taromaru"ようなURLに変数を入れるようなものを実装してみよう。といってもとても簡単にできる。

#!/usr/bin/python3

# -*- coding: utf-8 -*-

from flask import Flask
app = Flask(__name__)

@app.route('/user/<username>')
def show_user_profile(username):
return 'User ' + str(username)

if __name__ == "__main__":
app.run(debug=True)

これを実行し http://127.0.0.1:5000/user/taromaru にアクセスするとちゃんといい感じに表示される。taromaruの部分をいじって遊んで見てほしい。

このようにURLのうち変数にしたい部分を「<>」で囲み、デコレートされる関数の引数としてその名前を指定すればいいだけだ。


リダイレクト

あるページに来たリクエストを条件によって別なページに転送したいというようなことがあるかもしれない。具体例としては認証が必要なページにアクセスが来た際にまだ認証が済んでいない場合、ログインページにとばすなどだ。

そういう時に便利な機能がリダイレクトだ。

#!/usr/bin/python3

# -*- coding: utf-8 -*-

from flask import Flask, redirect

app = Flask(__name__)

@app.route("/")
def index():
return redirect("/login")

@app.route("/login")
def login():
return "login"

if __name__ == "__main__":
app.run(debug=True)

http://127.0.0.1:5000/ にアクセスしたのに/loginに飛ばされたはずだ。このようにredirectをつかって飛ばしたいURLを指定すれば良い。


関数名からURLを得る

プログラムを作成しているとURLをかえたいことが多々あると思う。そのような場合にプログラム中にハードコーディングされているURLを書き換えていくのはミスを誘発しやすい。そうでなくても非常にだるい作業だ。そこで、便利なのが関数名からそれに紐付いているURLに変換してくれるurl_for関数だ。つまりが関数名を文字列として渡すとルーティング先を文字列として返してくれる。

単純な例だが以下のように使える。

#!/usr/bin/python3

# -*- coding: utf-8 -*-

from flask import Flask, url_for

app = Flask(__name__)

@app.route("/")
def index():
return url_for("index")

if __name__ == "__main__":
app.run(debug=True)

この例ではindexという関数名をurl_forにわたすことによって「/」というルーティング先を得ることができている。


確認問題

下記のプログラムの動作を予想せよ。

また、実際に実行してみて「 http://127.0.0.1:5000/ 」にアクセスしたときの動作を確かめよ。

# -*- coding: utf-8 -*-

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

@app.route('/')
def index():
return redirect(url_for("func"))

@app.route('/hello')
def func():
return "hello"

if __name__ == "__main__":
app.run(debug=True)


問題



  • http://127.0.0.1:5000/profile/user_name にアクセスが来た場合「Hello user_name!」を表示するようなプログラムをかけ(user_nameは可変)

  • 次のようにディクショナリでIDとパスワードが与えられる。
    http://127.0.0.1:5000/login?id=hoge&pass=foo のようなURLに対してアクセスが来た際、ログインに成功すれば /success に失敗すれば /failに飛ばすようにせよ

  • 2問目をurl_forを使っていない場合url_forをつかって書きなおせ

user_data = [{"id":"zako","pass":"week_pass"},{"id":"ikarochan","pass":"kawaii"},{"id":"miku","pass":"hatsune"}]


発展


  • プログラム中によく出てくる「_main_」とはなんなのかモジュールとの関連で調べよ。