FlaskでWebサービスを作るときのメモ・参考集

**WIP**

# はじめに

Flaskを使ってWebサーバーを書くことが多いので、よく参考にするページをまとめておきます。
とりあえずはリンク集になるかと思いますが、時間があれば内容も書き足して行きたいです。
（そろそろ[FastAPI](https://fastapi.tiangolo.com/)つかってみたい）

# 主な環境
* Python 3.8 (pipenv, pyenv)
* Flask
* MySQL 8.0 - SQLAlchemy
* gunicorn
* Nginx
* (Docker, docker-compose)
* Ubuntu 20.04 LTS


# Flaskまわり

* `SECRET_KEY`について
公式チュートリアルには、`os.urandom(12)`を用いるのが良いとされているが、これは**アンチパターン**
gunicornを複数のWorkderで動かしたときに、workerによって異なるSECRET_KEYが設定されてしまうため、SessionやCSRFProtection(Flask-WTF)が正常に動かない

* [便利な拡張集](https://nickjanetakis.com/blog/15-useful-flask-extensions-and-libraries-that-i-use-in-every-project)
* [socket.io](https://flask-socketio.readthedocs.io/en/latest/)

## session

### ブラウザセッション
プラグインを何も入れていないバニラのFlaskでは
* cookie session
* base64encode
となっている。
公式Docには`app.Config`に`SecretKey`を設定する旨が記載されているが、これはsessionに格納された内容の改竄を防ぐためのhash計算にこのキーを用いているだけであり、sessionの中身自体が暗号化されるわけではない。

### server session
プラグインを導入する必要がある。sessionを保存するバックエンドの選択肢としては、Redis, その他NoSQL, FileSystem, SQL等がある

有名所のプラグインとしては

* [Flask-Session](https://pythonhosted.org/Flask-Session/)
* [beaker](https://beaker.readthedocs.io/en/latest/index.html)

などがある。FLask-Sessionは、Sessionを保持するバックエンドに対してFlask内からアクセスするが、Beakerは使用するWSGI(例えばGunicorn)のミドルウェアとして動作する。
また後者はCache機能も提供する。
なお、Flask-Sessionは、バックエンドにSQLAlchemyを指定した場合（つまりSQL）正しく動作しないバグが確認されている。(2020.5月時点）

## logging
Flaskやそのプラグインは、ログ出力機能が提供されていることが多い。出力されているログをFlask本体のログハンドルで捉えて出力させるには、

```python
import logging
from flask.logging import default_handler #flask本体のログハンドラ
# その他のimportなど
from flask_cors import CORS

def create_app():
    # init_app等の諸々の処理
    # ここでは、ログを取りたいプラグインを`flask_cors`とする
    cors_err_lggr = logger.getLogger('flask_cors')
    # 大体のプラグインは内蔵loggerの名前を__name__で指定している？
    cors_err_lggr.setLever(logging.DEBUG)
    # デフォルトのログハンドラを追加
    cors_err_lggr.addHandler(default_handler)
    
    # その他諸々の処理

    return app
```

## test


# DB(MySQL, SQLAlchemy)まわり

* [SQLAlchemy relationship 公式Doc](https://docs.sqlalchemy.org/en/13/orm/basic_relationships.html)
* [SQLAlchemy many:many relation 解説記事](https://momijiame.tumblr.com/post/27327972441/python-%E3%81%AE-or%E3%83%9E%E3%83%83%E3%83%91%E3%83%BC-sqlalchemy-%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%9F%E3%83%AA%E3%83%AC%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%8A%E3%83%AB%E3%83%9E%E3%83%83%E3%83%94%E3%83%B3%E3%82%B0%E5%9F%BA%E6%9C%AC-4)
* [SQLAlchemy relation パラメタの解説が詳しい](https://poyo.hatenablog.jp/entry/2017/01/08/212227)
* ~~[N:N中間テーブルに存在する独立したカラムを取得する変わり種](https://qiita.com/shirakiya/items/6faf3ed05e959f135e52)~~

many:manyの中間テーブルに、独立したカラム(ForeignKeyでないカラム）を設定する場合、`relation`を用いるよりも、`association_proxy`を使ったほうが良い。
[association_proxyに関する公式Doc、実装例付き](https://docs.sqlalchemy.org/en/13/orm/extensions/associationproxy.html#simplifying-association-objects)


# Nginx, Gunicornまわり

* [Fabricを用いずに、Gunicornをvirtualenv上でホットデプロイするコード？] (http://wingu.github.io/zero-downtime-gunicorn.html)
* [gunicorn kill -HUP restart](http://tech.kakadu.jp/entry/2015/09/20/170107)

# Dockerまわり

# デプロイまわり
* Fabric2がいいらしい？

[公式ドキュメント](http://www.fabfile.org/)
CapistranoとかDeployerみたいな感じ
[解説記事1](https://nnsnodnb.hatenablog.jp/entry/deploy-product-with-fabric-2-4-0)
[解説記事2](https://qiita.com/navitime_tech/items/f15a97251542ae9668e4)




# おわりに
いや、[FastAPI](https://fastapi.tiangolo.com/)良くないか？