LoginSignup
5
7

More than 3 years have passed since last update.

Flask(v1.1.x)+SQLAlchemyでのdb.create_all()ができない

Posted at

概要

Flask(v1.1.x)のチュートリアルを大体やった後、以下の記事を参考にFlask(v1.1.x)+SQLAlchemyでWebアプリを開発途中、

python
>>> from app import db
>>> db.create_al()

でdbがインストールできず、その次のdb.create_all()もできませんでした。。。(記事自体は非常に丁寧でとても参考になりました。)
調べたけどもFlaskのバージョン1.1.xに対応した記事は特になかったので同じような人がいた場合の参考にまとめます。

参考記事

FlaskとPostgreSQLでウェブアプリを作ってHerokuで無料で運用する - Qiita

環境

  • OS : MaxOS Catalina version 10.15.1
  • Python : 3.7.7
  • Flask==1.1.2
  • Flask-SQLAlchemy==2.4.1

前提

途中(アプリの作成やデータベースの作成)コードについては参考記事をみてください。
以下は、参考記事をもとに作成したアプリケーションのディレクトリ構成です。

(any directory)/
├── flaskmemoapp/
├     ├── __init__.py
├     ├── model.py
├     └── templates/
├         └── index.html
├── Procfile
├── requirements.txt
├── runtime.txt
├── .git/
├── .gitignore
└── venv/

また、__init__.pymodel.pyは以下のようになりました。

init.py

__init__.py
import os
from flask import Flask, render_template, g, request, redirect, url_for
from flask_sqlalchemy import SQLAlchemy
from memo.model import init_db, Entry, db

def create_app():
    app = Flask(__name__, instance_relative_config=True)

    db_uri = os.environ.get(DATABASE_URL) or postgresql://localhost/flaskmemo
    app.config[SQLALCHEMY_DATABASE_URI] = db_uri
    init_db(app)

    @app.route(/)
    def hello_world():
        entries = Entry.query.all()
        return render_template('index.html', entries=entries)

    @app.route('/post', methods=['POST'])
    def add_entry():
        entry = Entry()
        entry.title = request.form[title]
        entry.body = request.form['body']
        db.session.add(entry)
        db.session.commit()
        return redirect(url_for('hello_world'))

    return app

model.py

model.py

from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()

def init_db(app):
        db.init_app(app)

class Entry(db.Model):
        __tablename__ = "entries"
        id = db.Column(db.Integer, primary_key=True)
        title = db.Column(db.String(), nullable=False)
        body = db.Column(db.String(), nullable=False)

解決方法

どうやらコマンドpythonで開くREPL環境ではいけないらしく、flask shellを使わないといけないらしい(詳細についてはあまりわかってません)。

実際にpythonのREPL環境とflask runで開くREPL環境では以下のような違いがありました。

コマンド python

~ $ python
Python 3.7.7 (default, May 19 2020, 10:55:09) 
[GCC 7.5.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from flaskmemoapp.model import db
>>> db
<SQLAlchemy engine=None>

コマンド flask shell

$ export FLASK_APP=flaskmemoapp
$ flask shell
Python 3.7.7 (default, May 19 2020, 10:55:09) 
[GCC 7.5.0] on linux
App: flaskmemoapp [production]
Instance: /app/instance
>>> from memo.model import db
>>> db
<SQLAlchemy engine=postgres://hogehoge~>

コードを比較してみると、今回はPostgreSQLを使ったのですがpythonのREPL環境ではSQLAlchemyはpostgreSQLのデータベースのパスが入っていません。
どうやら今回のようなコードの場合はアプリのコンテキストなるものが必要になるらしく、それはflask shellの場合しかアプリのコンテキストで動作するREPL環境を起動してくれないようです。(表面的なことしかわかってないです。。。)

最終的にはflask shell

$ flask shell
>>> from memo.model import db
>>> db.create_all()

とするとデータベースが作成されました。

終わりに

Flaskのv1.1.xはまだ出たて(?)のためかあまりQiita内でも情報が探せず、荒い内容の記事にはなったのですが誰かの役に立てれば幸いです。
間違いや補足などがあればコメントお願いします!!!

5
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
5
7