Nginx + uWSGI + SQLAlchemy（MySQL）環境下でFlask-RESTfulのハローワールドを作成する

Flask-RESTfulのサンプルがあんまりなかったので、作成しました。
まだまだ拙いですが、まとめます。
# 環境構築
vagrantでCentOS7を構築。その上で、nginxとPython3.6とMySQLを入れます。
vagrantについては割愛します。
MySQLについても、どうやったか忘れてしまいました。。。
MariaDBではなくMySQLにしたのでググって入れたと思います。今回はどちらでも構わないので、お好きな方を用意してください。
### nginxのインストール
これは特に何も考えず、yumで入れました。

```
yum install nginx
```

### Python3.6のインストール
<a href="https://weblabo.oscasierra.net/python3-centos7-yum-install/">こちらのサイト</a>を参考にしました。
ありがとうございます。

まずはリポジトリを追加します。

```bash
yum install -y https://centos7.iuscommunity.org/ius-release.rpm
```
その後インストールします。

```bash
yum install python36u python36u-libs python36u-devel python36u-pip
```
※執筆時点では、Python3.6.2が入りました。
これで、以下のコマンドが使えるようになります。
* python3.6
* pip3.6
※普通にpythonとやると、CentOS7に初めから入っているPython2系が動いてしまいますので注意してください。

### Pythonモジュールのインストール
以下コマンドで入れました。

```bash
pip3.6 install flask
pip3.6 install flask-restful
pip3.6 install pymysql
pip3.6 install sqlalchemy
pip3.6 install uwsgi
```
なんとなくまとめてではなく分けましたが、特に意味はありません。
上記を実行後、`pip3.6 freeze`で確認すると、以下のような感じでした。
※他にも入れた状態から抜粋しているので、必ずしも同じではないかもしれません。

```
aniso8601==1.2.1
click==6.7
Flask==0.12.2
Flask-RESTful==0.3.6
itsdangerous==0.24
Jinja2==2.9.6
MarkupSafe==1.0
mccabe==0.2.1
pbr==3.1.1
pyflakes==0.8.1
PyMySQL==0.7.11
python-dateutil==2.6.1
pytz==2017.2
six==1.10.0
SQLAlchemy==1.1.13
uWSGI==2.0.15
Werkzeug==0.12.2
```
### MySQLの設定
my.cnfに以下を追加しておきます。場所は`/etc/my.cnf`か`/etc/my.cnf.d/`配下にあると思います。

```ini
[mysqld]
# ～中略～
character-set-server=utf8  # ここを追加

[client]  # ここを追加
default-character-set=utf8  # ここを追加
```

また、アプリケーションから接続するためのデータベースとユーザーを作っておきます。
mysqlにrootでログイン後、以下のSQLを実行します。

```sql
create database test;  -- testデータベースの作成
grant all privileges on test.* to admin@localhost identified by 'Adm!n2017' with grant option;
/* localからtestデータベースへ接続して何でもできるadminユーザーを
Adm!n2017というパスワードでログインできるようにして作成します*/
```
パスワードはMySQLのルールが厳しくて適当に作ったものなので、まあ参考までに。
権限は、正直そんなに理解してないのですがおそらくこんな感じだったと思います。
### nginxの設定
nginxに関しては、`/etc/nginx/nginx.conf`にちょっと付け足すだけです。

```ini
http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 2048;

    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;

    # Load modular configuration files from the /etc/nginx/conf.d directory.
    # See http://nginx.org/en/docs/ngx_core_module.html#include
    # for more information.
    include /etc/nginx/conf.d/*.conf;

    server {
        listen       80 default_server;
        listen       [::]:80 default_server;
        server_name  _;
        root         /usr/share/nginx/html;

        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;

        location / {
            include uwsgi_params;  # ここを追加
            uwsgi_pass unix:/usr/lib64/nginx/tmp/uwsgi.sock;  # ここを追加
```
だいぶ端折りましたが、locationのところに2行追加しただけですね。
uwsgi-passに関しては、お好みで変えてください。自分は/tmpの下とかにしたらnginxがアクセスできなかったのでここになりました。
uwsgiとnginxがやり取りするためのソケットの指定なので、やり取りできればどこでもいいと思います。
### IPアドレスについて
vagrantで仮想環境を作成したら、Virtualbox上で設定をいじれると思います。
確認しやすくするため、ネットワークアダプターを「ブリッジアダプター」に変更し、ホストと同じセグメントにします。
これは他の手段をお持ちなら行わなくても構いません。

# コーディング
ここでようやくコーディングですが、説明といっても難しいので、<a href="https://github.com/landwarrior/flask-restful-sample">ソースをGitHubで公開しています</a>のでそちらからダウンロードしてみてください。。。
### ソース配置場所
コーディングについて、ちょっと注意点がありました。
uwsgiを動かす時に使うuwsgi.iniというファイルがありますが、その中で

```ini
chdir = /var/www/uwsgi-restful
```
と指定していますので、ソース配置場所はこの場合`/var/www/uwsgi-restful`になります。
ここは環境に合わせて変更してください。

# 動作確認
動かし方の正しい方法がよく理解できていないのですが、実際に動いている方法を書きます。
まずは、nginxを起動しましょう。

```bash
systemctl start nginx
```
次に、uwsgiを動かします。

```bash
cd /var/www/uwsgi-restful
uwsgi --ini uwsgi.ini
```
GitHubで公開しているソースありきになってしまい恐縮ですが、これで動き出します。
ちなみに、この時にMySQLに用意したtestデータベースに、model.pyで定義したusersテーブルがなければ作成されます。

動いている間はターミナルが使えないので、もう一つターミナルを用意しましょう。
<a href="https://github.com/landwarrior/flask-restful-sample">GitHub</a>で公開しているソースのtestsディレクトリにあるsample.pyを見てみてください。

```py
"""とりあえずテスト用."""

import json

import requests





def get():

    """GETメソッドで問い合わせる."""

    headers = {'Content-Type': 'application/json; utf-8'}

    # URLは環境に合わせて変更してください

    result = requests.get('http://192.168.0.204/hello', headers=headers)

    print(result.status_code)

    print(result.headers['Content-Type'])

    print(result.content)

    print(result.json())





def post():

    """POSTメソッドで問い合わせる."""

    data = {'user_name': 'テスト', 'password': 'test', 'active': 1}

    headers = {'Content-Type': 'application/json; utf-8'}

    # URLは環境に合わせて変更してください

    result = requests.post('http://192.168.0.204/hello',

                           data=json.dumps(data), headers=headers)

    print(result.status_code)

    print(result.headers['Content-Type'])

    print(result.content)

    print(result.json())





if __name__ == '__main__':

    get()

    post()
```
ユニットテストではなくひとまずの動作確認なのでやっつけですが。。。
URLやパラメーターなんかは適当にいじってもらって、適当にsample.pyを実行してもらうと、Flask-RESTfulからの応答が確認できると思います。
MySQLでレコードを見ると、データが挿入されています。

```bash
mysql> select * from users;
+---------+------------+----------+--------+-------------+-------------+-------------+
| user_id | user_name  | password | active | create_date | update_date | delete_date |
+---------+------------+----------+--------+-------------+-------------+-------------+
|       1 | テスト     | test     |      1 | NULL        | NULL        | NULL        |
+---------+------------+----------+--------+-------------+-------------+-------------+
6 rows in set (0.00 sec)
```

# 終わりに
本当はDockerコンテナ上で色々構築したかったのですが、そこまでは手付かずです・・・
本稿を執筆中にも間違いを直して<a href="https://github.com/landwarrior/flask-restful-sample">GitHub</a>にコミットしたりしてました・・・
なお、<a href="https://github.com/landwarrior/flask-restful-sample">GitHub</a>上のWikiにも似たようなことを書いてありますが、こちらではより詳細に記載しておきました。