Flaskを用いたウェブアプリケーション作成②

# 7. データベース操作
データベースを設定し使えるようにしました。
記事のデータをデータベースに保存し、データベースからデータを取り出すための処理を行いました。
# 7-1. SQLAlchemy
データベースの操作には**SQLAlchamy**を用いました。
#### 7-1-1. SQLAlchemyの初期設定
config.pyにて以下のように設定します。
今回は**SQLite**というデータベースを使用しました。

```python:./cafesite/config.py
# DBファイルの参照先を指定
SQLALCHEMY_DATABASE_URI = 'sqlite:///cafe_site.db'
SQLALCHEMY_TRACK_MODIFICATIONS = True
DEBUG = True
SECRET_KEY = 'secret key'
USERNAME = 'john'
PASSWORD = 'abc123'
```
**__init__.py** も編集します。

```python:./cafesite/config.py
from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config.from_object('cafe_site.config')

# db変数作成
db = SQLAlchemy(app)

import cafe_site.views
```
SQLAlchemyライブラリをインストールし、`db = SQLAlchemy(app)`と記述することでdb変数からデータベースを操作出来るようにしました。
# 8. モデル作成(MTVにおけるModel)
次に、データベースのモデルを定義します。
記事には**タイトル**、**本文**、**投稿日時**の3つの属性を付与しました。この属性をデータベースモデルに定義します。
## 8-1. モデル定義
記事のモデルを作成します。
**cafe_site**フォルダ以下に**models**フォルダを作成し、その中に**reviews.py**ファイルを作成します。

```python:./cafesite/models/reviews.py
from cafe_site import db
from datetime import datetime

class Review(db.Model):
# テーブル定義
    __tablename__ = 'Reviews'
# idを主キーとして定義
    id = db.Column(db.Integer, primary_key=True)
# titleにユニーク制約を定義
    title = db.Column(db.String(50), unique=True)
    text = db.Column(db.Text)
    created_at = db.Column(db.DateTime)

# モデルの標準動作を定義
    def __init__(self, title=None, text=None):
        self.title = title
        self.text = text
        self.created_at = datetime.utcnow()

# 参照時の表示フォーマット定義
    def __repr__(self):
        return '<Review id:{} title:{} text:{}>'.format(self.id, self.title, self.text)
```
`class Review(db.Model):`でモデルを定義し`__tablename__ = 'Reviews'`でデータベースに格納されるテーブルの名前をつけています。
## 8-2. 属性定義
```python:./cafesite/models/reviews.py
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(50), unique=True)
    text = db.Column(db.Text)
    created_at = db.Column(db.DateTime)
```
データを取り出すときは、主キーである`id`を使います。
2行目以降もルールに従って属性を定義して行きます。
`unique=True`はユニーク制約の処理です。
## 8-3. モデル作成後の処理
`def __init__(self, title=None, text=None):`でモデルが作成された時の標準動作を定義します。

```python:./cafesite/models/reviews.py
def __init__(self, title=None, text=None):
        self.title = title
        self.text = text
        self.created_at = datetime.utcnow()
```
この定義により、今後以下のように書くことで、指定したタイトルと内容かつ現在の時間を投稿日時として記事データが作成されるようになりました。

```markdown
Review(title="記事のタイトル", text="記事の内容")
```
## 8-4. 参照されたときの表示フォーマットを定義する

```python:./cafesite/models/reviews.py
def __repr__(self):
        return '<Review id:{} title:{} text:{}>'.format(self.id, self.title, self.text)
```
ここでは、**id**と**タイトル**と**テキスト**をコンソールで表示されるようにしています。
## 8-5. 決まった処理を共通して使えるようするスクリプトの作成
cafe_site以下に**scripts**フォルダを作成し、その中に**db.py**ファイルを作成します。

```python:./cafe_site/scripts/db.py
from flask_script import Command
from cafe_site import db

# db作成モジュール定義
class InitDB(Command):
    "create database"

# 実行時の処理
    def run(self):
        db.create_all()
```
`class InitDB(Command):`とクラスを定義しました。`(Command)`とすることで、スクリプト実行のためのクラスとして定義されます。
`"createdatabse"`は、クラスの説明のためのコメントです。

`def run(self):`は、実際にスクリプトで実行される内容になります。実行内容として`db.create_all()`とし、モデル定義がデータベースに反映されるようにしました。

## 8-6. manage.py作成
次に作成したscripts.pyをコンソール上で実行できるようにしました。
rootディレクトリ直下に**manage.py**という名前のファイルを作成します。

```python:./manage.py
from flask_script import Manager
from cafe_site import app
from cafe_site.scripts.db import InitDB

# スクリプト単体で実行時の処理
if __name__ == "__main__":
    manager = Manager(app)
# db作成コマンド定義
    manager.add_command('init_db', InitDB())
    manager.run()
```

`if__name__=="__main__":`でスクリプトファイルを登録しています。`manager.add_command('init_db',InitDB())`とすることで、作成したInitDB()モジュールをinit_dbという名前で実行できるようにしました。

```bash:コンソール
python manage.py init_db
```
実行後cafe_siteフォルダ以下に**cafe_site.db**ファイルが作成されます。
> 続きは[Flaskを用いたウェブアプリケーション作成③](https://qiita.com/syu-hei/items/cf57ac171d357bca8b1a)で説明いたします。