flaskチュートリアルをやってみた
タイトルにもある通りFlaskのチュートリアルを進めたのですが、日本語版チュートリアルは情報が古くうまく動かない部分などがあったため、それらの点を解説しつつブログアプリflaskrを作成していきます。
#step0
チュートリアルではディレクトリ構成を解説しています。
この点は問題はありません。
manage.py
requirements.txt
flaskr/
|- __init__.py
|- config.py
|- views.py
|- models.py
|- static/
|- style.css
|- templates/
|- layout.html
|- show_entries.html
特筆するまでもないですが、flaskはtemplates以下のhtmlファイルを参照するようにできているのでそれ以外のフォルダ名だと動きません。
##requirements.txt
ここも問題はありません。
Flask
Flask-SQLAlchemy
以下のコマンドでインストールしてください。
pip install -r requirements.txt
##manage.py
このファイルを実行することでflaskrというブログアプリを動かします。
from flaskr import app
app.run(host='127.0.0.1', port=5000, debug=True)
##flaskr/init.py
ここでは1つ注意する点があります。
チュートリアル通りに作成すると実行した際に以下のようなエラーが起きます。
ModuleNotFoundError: No module named 'flask.ext'
flask.ext.sqlalchemyの使用はあまり推奨されていないようです。
そのため、2行目を以下のように変更することでこのエラーは解消されます。
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config.from_object('flaskr.config')
db = SQLAlchemy(app)
import flaskr.views
flaskr/config.py
データベースの設定とセッション情報を暗号化するための情報などまとめてconfigfileで管理することができます。
SQLALCHEMY_DATABASE_URI = 'sqlite:///flaskr.db'
SECRET_KEY = 'secret key'
step1
ここからデータベースを作成していくみたいです。
flaskr/models.py
from flaskr import db
class Entry(db.Model):
__tablename__ = 'entries'
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.Text)
text = db.Column(db.Text)
def __repr__(self):
return '<Entry id={id} title={title!r}>'.format(
id=self.id, title=self.title)
def init():
db.create_all()
注意点として、上記のコードを書いた段階ではまだデータベースはできていません。
その状態でアプリを起動すると以下のようなエラーが表示されます。
sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) no such table: entries
忘れずにターミナルで以下のように打ち込んでデータベースファイルの作成を行なってください。
$ python
>>> from flaskr.models import init
>>> init()
チュートリアルではここで動作の確認を行なっていますが、これはやってもやらなくても問題ありません。
step2
ここではブログの一覧と投稿画面を作ります。
flaskr/views.py
ここも特に問題はありません。チュートリアルの通り進めてください。
from flask import request, redirect, url_for, render_template, flash
from flaskr import app, db
from flaskr.models import Entry
@app.route('/')
def show_entries():
entries = Entry.query.order_by(Entry.id.desc()).all()
return render_template('show_entries.html', entries=entries)
@app.route('/add', methods=['POST'])
def add_entry():
entry = Entry(
title=request.form['title'],
text=request.form['text']
)
db.session.add(entry)
db.session.commit()
flash('New entry was successfully posted')
return redirect(url_for('show_entries'))
step3
htmlとcss、ブログの機能ではなくて表側をいじっていきます。
##flaskr/template/layout.html
<!doctype html>
<title>Flaskr</title>
<link rel=stylesheet type=text/css href="{{ url_for('static', filename='style.css') }}">
<div class=page>
<h1>Flaskr</h1>
{% for message in get_flashed_messages() %}
<div class=flash>{{ message }}</div>
{% endfor %}
{% block body %}{% endblock %}
</div>
##flaskr/templates/show_entries.html
{% extends "layout.html" %}
{% block body %}
<form action="{{ url_for('add_entry') }}" method=post class=add-entry>
<dl>
<dt>Title:
<dd><input type=text size=20 name=title>
<dt>Text:
<dd><textarea name=text rows=5 cols=20></textarea>
<dd><input type=submit value=Share>
</dl>
</form>
<ul class=entries>
{% for entry in entries %}
<li><h2>{{ entry.title }}</h2>{{ entry.text|safe }}
{% else %}
<li><em>Unbelievable. No entries here so far</em>
{% endfor %}
</ul>
{% endblock %}
##flaskr/static/style.css
body { font-family: sans-serif; background: #eee; }
a, h1, h2 { color: #377ba8; }
h1, h2 { font-family: 'Georgia', serif; margin: 0; }
h1 { border-bottom: 2px solid #eee; }
h2 { font-size: 1.2em; }
.page { margin: 2em auto; width: 35em; border: 5px solid #ccc;
padding: 0.8em; background: white; }
.entries { list-style: none; margin: 0; padding: 0; }
.entries li { margin: 0.8em 1.2em; }
.entries li h2 { margin-left: -1em; }
.add-entry { font-size: 0.9em; border-bottom: 1px solid #ccc; }
.add-entry dl { font-weight: bold; }
.metanav { text-align: right; font-size: 0.8em; padding: 0.3em;
margin-bottom: 1em; background: #fafafa; }
.flash { background: #cee5F5; padding: 0.5em;
border: 1px solid #aacbe2; }
.error { background: #f0d6d6; padding: 0.5em; }
あとはチュートリアルの最後にあるように以下のように打ち込むことで問題なく動くと思われます。
python manage.py
# 自分がつまづいた点
##その1
No module named flask
上記のようにエラーが出た場合はpythonのバージョンが混在している等の問題がある可能性があります。
非常に基本的な部分なのですがmacだと初期状態でpythonが2.7なのでpython3をデフォルトにする必要がありました。(必須ではないのですがpython3で統一している方が何かと便利なので)
基本的に上のリンクに従って進めて、もしもエラーが出てしまった場合は下のリンクで解決できると思います。
##その2
OSError: [Errno 48] Address already in use
上記のエラーはアプリを前回起動した時のプロセス(なんか邪魔なものくらいの認識で大丈夫です)が残っている状態です。アプリを起動している状態でコードをいじったりしてまうとこのようになる可能性があります。
$ lsof -i:5000
そのためこのようにターミナルで打ち込んで使用中のプロセスを切ってあげましょう。
python3.7 23820 kinouchiyuta 3u IPv4 0xa9d666bd1529b1a1 0t0 TCP localhost:commplex-main (LISTEN)
python3.7 23836 kinouchiyuta 3u IPv4 0xa9d666bd1529b1a1 0t0 TCP localhost:commplex-main (LISTEN)
python3.7 23836 kinouchiyuta 4u IPv4 0xa9d666bd1529b1a1 0t0 TCP localhost:commplex-main (LISTEN)
このように使用中のプロセスが出てきたら
$ kill -9 [該当のID]
今回だと以下のように打ち込めば問題ないですね。
$ kill -9 23820
$ kill -9 23836