31
Help us understand the problem. What are the problem?

More than 5 years have passed since last update.

posted at

updated at

PostgreSQLを用いたFlaskアプリのHerokuデプロイ(Flask-SQLAlchemy)

はじめに

Postgresを使ったFlaskのアプリケーションをHerokuデプロイにはまっていたのでメモ。
Flask-SQLAlchemyというFlask拡張ORMを使います。
Flask-SQLAlchemy公式よりこのサイトの方がわかりやすかった。
FlaskのインストールやDBを使わないHerokuデプロイは既にできている状態から始めます。

簡単な用語の説明

  • SQLAlchemy
    • PythonのためのDBツールキットでありORM
  • flask-sqlalchem
    • SQLAlchemyをFlaskで動かすための拡張
  • psycopg
    • Python用のPostgreSQLアダプタ

ライブラリのインストール

$ pip install flask-sqlalchemy psycopg2

requirements.txtを書き込みするFlaskでのおきまりの作業

$ pip freeze > requirements.txt

データベース接続・モデル作成・データ挿入

Userモデルとユーザーidに紐づくTaskモデルという2つのモデルを扱う例です。
Herokuでうまくいくには以下のようにDATABASE_URLを明示してDB接続をする必要があります。
app.config['SQLALCHEMY_DATABASE_URI'] = os.environ['DATABASE_URL']

app.py
from flask.ext.sqlalchemy import SQLAlchemy
from flask import Flask, render_template, request

# DB接続に関する部分
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = os.environ['DATABASE_URL']
db = SQLAlchemy(app)

# モデル作成
class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(80), unique=True)
    email = db.Column(db.String(80), unique=True)

    def __init__(self, username, email):
        self.username = username
        self.email = email

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

class Task(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    tasks = db.Column(db.String(80))
    user_id = db.Column(db.Integer,db.ForeignKey('user.id'))

    def __init__(self, tasks, user_id):
        self.tasks = tasks
        self.user_id = user_id

    def __repr__(self):
        return '<Task %r>' % self.tasks

# データベースに追加するコード例
@app.route("/", methods=['POST'])
def register():
    if request.method == 'POST':
        name= request.form['name']
       email = request.form['email']
      task = request.form['task']
        # emailが未登録ならユーザー追加
       if not db.session.query(User).filter(User.email == email).count():
            reg = User(name, email)
            db.session.add(reg)
            db.session.commit()


        # タスク追加
        user_id= User.query.filter_by(User.email == email).first().id
        task = Task(text, user_id)
        db.session.add(task)
        db.session.commit()

        return render_template('success.html')  return render_template('index.html')

if __name__ == '__main__':
    app.debug = True
    app.run()

モデルの作成やデータの挿入は以下のflask-sqlalchemyのドキュメントを参考にしました
* アソシエーション
* 選択、挿入、削除

Herokuに反映

$ git commit -a -m "added DB boilerplate"
$ git push heroku master

Heroku側にPostgresのアドオンを追加

$ heroku addons:add heroku-postgresql

Heroku先でDBの作成を行う

$heroku run python
>>> from app-name import db
>>> db.create_all()

これでHerokuでもうまく動いているはずです。
以下のようにしてもDB操作が可能です

$heroku run python
>>> from app-name import db,User,Task
>>> User.query.all()
[<User 'userxx'>]
>>> Task.query.all()
...

よく使ったHerokuコマンド(蛇足)

  • heroku run bash
    • heroku先にsshみたいな
  • heroku logs -t
    • Herokuのログの確認
  • heroku pg:reset DATABASE --confirm app-name
    • databaseのリセット

参考にしたサイト

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
31
Help us understand the problem. What are the problem?