Flask（自分用のメモ）

# その前に基礎知識
- ルーティング: ウェブブラウザからのリクエストに合わせて呼び出す処理を切り替える機能
    - URLと処理を紐付ける機能
- テンプレートエンジン：アプリケーションが保持するデータ、プログラムが処理した結果をHTMLの雛形を組み合わせてウェブページとして表示する機能



#　いろいろ

```
$env:FLASK_APP="app"
flask run
```

```python:app.py
from flask import Flask

app = Flask(__name__)  # アプリケーションオブジェクトの取得

@app.route('/')  # ルーティング
def hello():
	return "hello world!"
```

## Flask_APP 
- 環境変数
    - OSが動いているときに使える変数[「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典](https://wa3.i-3-i.info/word11027.html)
    - オペレーティングシステム (OS) が提供するデータ共有機能の一つ(wiki)
        - OS上で動作するタスク（プロセス）がデータを共有するための仕組みである。

- FLASK_APP
    - ウェブアプリのモジュール名を示す。
    - 今回は「app」
    - 未設定でapp.py が実行
    - 適当な値を入れたらアカンで。

- FLASK_ENV
    - FLASKを実行する環境構成を実行
        - production: 本番環境を対象とした構成
            - デバッグモードとリロードが有効になる。
                - デバッグモード：エラーの詳細をトレースできる。
                - リロードモード：スクリプトを編集したら自動でアプリケーションを再起動してくれる仕組み
        - development: 開発環境を対象とした構成
    - 未設定でproduction


##　ルーティング

```python
@app.route('/')  # URLのパスに相当
```
`/`はhttp://localhost:5000/に相当


#### URLの一部を変数として使う
```python
@app.route('/rt_variable/<var>')
def fn_variable(var):
	return var
```

型の制限を掛けられる。

```python:python
@app.route('/rt_variable/') 
@app.route('/rt_variable_i/<int:var>')　整数
@app.route('/rt_variable_f/<float:var>')　浮動小数点数
@app.route('/rt_variable_p/<path:var>')　任意のパス
@app.route('/rt_variable_u/<uuid:var>')　
@app.route('/rt_variable_a/<any(s1,s2,s3):var>')　この中のどれか
def fn_variable(var=None):
	print("*****called******")
	ans = str(var)
	return ans
```

## テンプレート
- テンプレート：htmlなどのウェブページに対応した雛形
    - pythonのコードを入れ込むことで、動的にウェブページを生成できる。

```python:app.py
@app.route('/ex_template/')
@app.route('/ex_template/<t1>')
def fn_template(t1=None):
	return render_template('template_example.html', var=t1) 
//出力するテンプレートと、テンプレート内で利用する変数
```

```html:template
<!doctype html>
<tytle>Template Example</tytle>
{% if var %}
<h1>var: {{var}}</h1>
{% else %}
<h1>var is None</h1>
{% endif %}

```

{{ }}はpythonの変数や実行結果を出力したいときに使う
{% %}は制御文を使いたいときに使う

## Requestオブジェクト
- httpリクエストのメソッド名、パラメーター、ヘッダ情報を取得できる。

```
Invoke-RestMethod -Uri "http://localhost:5000/ex_req?u1=abc&u2=def&u1=ghi" -Method POST -Body "f1=ABC
&f2=DEF&f2=GHIAAA"
```

```python:app.py
@app.route('/ex_req', methods=['GET', 'POST'])
def fn_req():
	print(request.method) //POST
	print(request.path) // /ex_req
	print(request.content_length) //23
	print(request.mimetype) // application/x-www-form-urlencoded

	print(request.args.get('u1')) //abc
	print(request.args['u2']) // def
	print(request.args.getlist('u1')) //['abc', 'ghi']

	print(request.form.get('f1')) // ABC
	print(request.form['f2']) // DEF
	print(request.form.getlist('f1')) //['ABC']

	print(request.headers.getlist('Connection'))　//['Keep-Alive']
	print(request.headers['Connection'])  // Keep-Alive
	print(request.headers.get('Connection')) //Keep-Alive

	return 'call fn_req()'
```


##　リダイレクト

```
@app.route('/ex_redirect')
def fn_redirect():
	return redirect (url_for('fn_rt_variable')) //リダイレクト先の関数
```


## ファイルアップロード
```python:app.py
@app.route('/ex_upload', methods=['GET', 'POST'])
def fn_upload():
	if request.method == 'POST' and 'file' in request.files:
		f = request.files['file'] //ファイルを取得
		f.save('upload_files/' + secure_filename(f.filename))　//保存。ディレクトリを指定。ファイル名はセキュアなものに直してくれる。
		return 'file uploaded'
```

## make responce関数
- レスポンスの内容を設定できる
    - レスポンスヘッダー
    - httpステータス


```python:app.py
@app.route('/ex_res/<int:var>')
def fn_res(var):
	resp = make_response('call fn_res().'.var) //varをhttpステータスに設定
	resp.headers["ex_res"] = "OK!!" // headerはex_resという名称で、OK!!を選択
	return resp 
```

```
StatusCode        : 200
StatusDescription : OK
Content           : call fn_res().
RawContent        : HTTP/1.0 200 OK
                    ex_res: OK!!
                    Content-Length: 14
                    Content-Type: text/html; charset=utf-8
                    Date: Wed, 19 Jun 2019 12:10:44 GMT
                    Server: Werkzeug/0.15.4 Python/3.7.3

                    call fn_res().
Forms             : {}
Headers           : {[ex_res, OK!!], [Content-Length, 14], [Content-Type, text/html; charset=utf-8], [Date, Wed, 19
                    Jun 2019 12:10:44 GMT]...} //[ex_res, OK!!]が追加されている。
Images            : {}
InputFields       : {}
Links             : {}
ParsedHtml        : mshtml.HTMLDocumentClass
RawContentLength  : 14
```


## クッキー

```python:app.py
@app.route('ex_cookie')
@app.route('ex_cookie/<var>')
def fn_cookie(var=None):
	if var is None:
		ck = request.cookies.get('ck') //cookieの取得。request内のgetメソッドで取得。
		return f"ck={ck}"
	resp = make_response('set_cookie')    // レスポンスオブジェクトの生成
	resp.set_cookie('ck', var) //cookieにデータを保存する。　「ck:var」って感じ
	return resp
```


## セッション

```python:app.py

app.secret_key = "test"  // セッションの暗号化で使う

@app.route('/ex_session')
def fn_session(var=None):
	if var is None:
		sess = session.get('sess')　//セッション取得
		return f"sess = {sess}"

	session["sess"] = ver　　//セッションへデータ保存
	return "set settion"
```


##　フラッシュ
- 一度だけ表示したいメッセージに使う

```python:app.py
app.secret_key = "test"

@app.route('/ex_flash')
@app.route('/ex_flash/<var>')
def fn_flash(var=None):
	if var is None:
		fl = get_flashed_messages()　//フラッシュの呼び出し。もう一度呼び出すと消える。
		return f"fl = {fl}"

	flash(var) //フラッシュの保存
	return "set settion"
```

## ロギング
- pythonのロギング機能を使うことができる。
    - ロギング：ログ出力のこと。

```python:app.py
@app.route('/ex_logging')
@app.route('/ex_logging/<var>')
def fn_logging(var=None):
	app.logger.info(var)
	app.logger.warning(var)
	app.logger.error(var)
	return "call fn_logging()"
'''