2. Flaskチュートリアル¶
Flask公式チュートリアルのFlaskrというブログアプリを作っていきます。
公式のチュートリアルではsqliteを直接使っていますが、 今回はSQLAlchemyを使っていきます。
Step 0¶
まずはディレクトリを作成します。
最終的なディレクトリとファイルは以下の様な構成となります。:
manage.py
requirements.txt
flaskr/
|- __init__.py
|- config.py
|- views.py
|- models.py
|- static/
|- style.css
|- templates/
|- layout.html
|- show_entries.html
以下の様な感じで作成します。:
cd 先ほどhelloworldディレクトリを作成したディレクトリ
mkdir -p tutorial/flaskr/{static,templates}
cd tutorial
touch manage.py requirements.txt
touch flaskr/{__init__,views,models,config}.py
touch flaskr/static/style.css
touch flaskr/templates/{layout,show_entries}.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¶
FlaskとプラグインのSQLAlchemyを生成します。
from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config.from_object('flaskr.config')
db = SQLAlchemy(app)
import flaskr.views
app.config.from_object(‘flaskr.config’)はFlaskのconfigが 設定ファイルを読み込む処理で、他にも以下のような処理があります。
- app.config.from_envvar: 環境変数から読み込む
- app.config.from_object: pythonオブジェクトから読み込む
- app.config.from_pyfile: pythonファイルから読み込む
flaskr/config.py¶
データベースの設定と、セッション情報を暗号化するためのキーを設定します。
SQLALCHEMY_DATABASE_URI = 'sqlite:///flaskr.db'
SECRET_KEY = 'secret key'
実際に運用する場合には、SECRET_KEYは必ず変更して下さい。
ちなみにFlaskのドキュメントには、以下のように生成すると良いと書かれています。:
>>> import os
>>> os.urandom(24)
'\xfd{H\flash: xe5<\x95\xf9\xe3\x96.5\xd1\x01O<!\xd5\xa2\xa0\x9fR"\xa1\xa8
その他のファイルとディレクトリ¶
views.pyとmodels.pyは空のファイルで作成して下さい。あとから記述していきます。
staticとtemplatesも空のディレクトリで作成して下さい。あとからcssやhtmlを追加します。
Step 1¶
flaskrはブログなので、ブログの記事(データ)を格納する データベースを作ります。
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()
作成したデータベース定義を読み込み、データベースファイルを作成します。:
$ python
>>> from flaskr.models import init
>>> init()
これで、flaskr/flaskr.dbが生成されてます。
動作を確認してみましょう。:
$ python
>>> from flaskr.models import Entry, db
>>> Entry.query.all()
[]
>>> entry = Entry(title='title', text='text')
>>> db.session.add(entry)
>>> db.session.commit()
>>> Entry.query.all()
[<Entry id=1 title=u'title'>]
>>> entry = Entry.query.get(1)
>>> entry
<Entry id=1 title=u'title'>
>>> entry.title = 'Hello world'
>>> db.session.add(entry)
>>> db.session.commit()
>>> Entry.query.all()
[<Entry id=1 title=u'Hello world'>]
>>> entry = Entry.query.filter(Entry.title == 'Hello world').first()
>>> entry
<Entry id=1 title=u'Hello world'>
>>> db.session.delete(entry)
>>> db.session.commit()
>>> Entry.query.all()
[]
Step 2¶
ブログの一覧と投稿画面を作ります。
投稿画面はログインしているときのみ操作できるようにします。
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'))
request: | HTTPリクエストオブジェクト methodやフォームデータにアクセスできる |
---|---|
render_template: | |
指定したHTMLテンプレートを使ってレスポンスを返す。 | |
redirect: | 指定したURLにリダイレクトするレスポンスを返す。 |
url_for: | 指定したエンドポイントに対するURLを返す。 |
abort: | 指定したHTTPステータスコードのエラーを返す。 |
flash: | メッセージを通知するための仕組み |
Step 3¶
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; }