LoginSignup
6
7

More than 3 years have passed since last update.

2.Flaskチュートリアルをやってみた(2019/7/30)

Last updated at Posted at 2019-07-30

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
6
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
7