Flask SQLAlchemy

参考

シェルで動作確認

Dockerコンテナのビルド

Flask on Dockerのブログ と同様にDockerfileを作り、ビルドする。

ファイルを作成

1
2
3
4
5
6
7
8
9
10
$ mkdir -p  ~/Sources/docker_flask/sqlalchemy
$ cd ~/Sources/docker_flask/sqlalchemy
$ cat << EOF > Dockerfile
FROM ubuntu:latest

RUN apt-get update
RUN apt-get install python3 python3-pip -y

RUN pip3 install flask flask_sqlalchemy
EOF

ビルド

1
$ sudo docker build . -t dobachi/flask_sqlalchemy:1.0

アプリ作成と実行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ mkdir apps
$ cat << EOF > apps/app.py
from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/test.db'
db = SQLAlchemy(app)

class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True, nullable=False)
email = db.Column(db.String(120), unique=True, nullable=False)

def __repr__(self):
return '<User %r>' % self.username
EOF

シェルを起動する。

1
$ sudo docker run -it --rm -p 5000:5000 -v $(pwd)/apps:/usr/local/apps -e "FLASK_APP=app.py" -w /usr/local/apps -e "LC_ALL=C.UTF-8" -e "LANG=UTF-8" dobachi/flask_sqlalchemy:1.0 /bin/bash

シェル内で動作確認。テーブルを作ってレコードを生成。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
>>> from app import db
/usr/local/lib/python3.6/dist-packages/flask_sqlalchemy/__init__.py:794: FSADeprecationWarning: SQLALCHEMY_TRACK_MODIFICATIONS adds significant overhead and will be disabled by default in the future. Set it to True or False to suppress this warning.
'SQLALCHEMY_TRACK_MODIFICATIONS adds significant overhead and '
>>> db.create_all()
>>> from app import User
>>> admin = User(username='admin', email='admin@example.com')
>>> guest = User(username='guest', email='guest@example.com')
>>> db.session.add(admin)
>>> db.session.add(guest)
>>> db.session.commit()
>>> User.query.all()
[<User 'admin'>, <User 'guest'>]
>>> User.query.filter_by(username='admin').first()
<User 'admin'>

sqlite3コマンドで接続して内容を確認。

1
2
3
4
5
6
7
8
9
root@a5d5ee81df78:/usr/local/apps# apt install sqlite3
root@a5d5ee81df78:/usr/local/apps# sqlite3 /tmp/test.db
sqlite> .databases
main: /tmp/test.db
sqlite> .tables
user
sqlite> select * from user;
1|admin|admin@example.com
2|guest|guest@example.com

アプリから動作確認

上記と同様の流れをアプリから動作確認する。 Dockerイメージは上記で作ったものをベースとする。

アプリ作成

ここでは/registにアクセスすると、登録画面が出て、 登録するとリスト(/list)が表示されるアプリを作成する。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
$ mkdir -p  ~/Sources/docker_flask/sqlalchemy_app
$ cd ~/Sources/docker_flask/sqlalchemy_app
$ mkdir apps
$ cat << EOF > apps/app.py
from flask import Flask, url_for, request, render_template, redirect
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/test.db'
db = SQLAlchemy(app)

class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True, nullable=False)
email = db.Column(db.String(120), unique=True, nullable=False)

def __repr__(self):
return '<User %r>' % self.username

db.create_all()

@app.route('/regist', methods=['POST', 'GET'])
def regist():
if request.method == 'POST':
user = User(username=request.form['username'], email=request.form['email'])
db.session.add(user)
db.session.commit()
return redirect(url_for('list'))
# the code below is executed if the request method
# was GET or the credentials were invalid
return render_template('regist.html')

@app.route('/list')
def list():
users = User.query.order_by(User.username).all()
return render_template('list.html', users=users)
EOF
$ mkdir -p apps/templates
$ cat << EOF > apps/templates/regist.html
<!doctype html>
<title>Registration</title>
<form action="/regist" method="post">
<div>username: <input type="text" name="username"></div>
<div>email: <input type="text" name="email"></div>
<input type="submit" value="send">
<input type="reset" value="reset">
</form>

<a href="/list">list</a>
EOF
$ cat << EOF > apps/templates/list.html
<!doctype html>
<title>List ordered by username</title>
<table>
<thead>
<tr>
<th>id</th>
<th>username</th>
<th>email</th>
</tr>
</thead>
<tbody>
{% for item in users %}
<tr>
<td>
{{ item.id }}
</td>
<td>
{{ item.username }}
</td>
<td>
{{ item.email }}
</td>
</tr>
{% endfor %}
</tbody>
</table>
<a href="/regist">registration</a>
EOF

実行

1
$ sudo docker run -it --rm -p 5000:5000 -v $(pwd)/apps:/usr/local/apps -e "FLASK_APP=app.py" -w /usr/local/apps -e "LC_ALL=C.UTF-8" -e "LANG=UTF-8" dobachi/flask_sqlalchemy:1.0 flask run --host 0.0.0.0

なお、上記の実装はエラーハンドリング等を一切実施していないので 例えば同じユーザ名、メールアドレスで登録しようとすると例外が生じる。

共有