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


## はじめに
Postgresを使ったFlaskのアプリケーションをHerokuデプロイにはまっていたのでメモ。
Flask-SQLAlchemyというFlask拡張ORMを使います。
[Flask-SQLAlchemy公式](http://flask-sqlalchemy.pocoo.org/)より[このサイト](http://blog.y3xz.com/blog/2012/08/16/flask-and-postgresql-on-heroku)の方がわかりやすかった。
FlaskのインストールやDBを使わないHerokuデプロイは既にできている状態から始めます。

## 簡単な用語の説明
- [SQLAlchemy](http://www.sqlalchemy.org/)
	- PythonのためのDBツールキットでありORM
- [flask-sqlalchem](http://flask-sqlalchemy.pocoo.org/)
	- SQLAlchemyをFlaskで動かすための拡張
- [psycopg](http://initd.org/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']`

```python: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のドキュメントを参考にしました
* [アソシエーション](http://flask-sqlalchemy.pocoo.org/2.1/models/)
* [選択、挿入、削除](http://flask-sqlalchemy.pocoo.org/2.1/queries/)


## Herokuに反映

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

Heroku側に[Postgresのアドオン](https://devcenter.heroku.com/articles/heroku-postgresql)を追加

```
$ 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のリセット

## 参考にしたサイト
* http://blog.y3xz.com/blog/2012/08/16/flask-and-postgresql-on-heroku
* http://blog.sahildiwan.com/posts/flask-and-postgresql-app-deployed-on-heroku/
* http://www.vertabelo.com/blog/technical-articles/web-app-development-with-flask-sqlalchemy-bootstrap-part-3