kuroの覚え書き

96の個人的覚え書き

データベース再び

前にもやったが

from flask_sqlalchemy import SQLAlchemy
#モジュール読み込み

SQLALCHEMY_DATABASE_URIというconfiguration keyでデータベースを読み込む
SQLiteを使うときにはsqlite:////absolute/path/to/databaseという感じに指定するわけだが
アプリケーションルートにdata.sqliteを作るなら
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///flaskr.db'
でもよいはず。(相対パスによる指定)

これをos.pathabspath(),os.path.dirname()メソッドを使うことでスクリプト(hello.py)の絶対パスを読み取っている。
なので

import os

basedir = os.path.abspath(os.path.dirname(__file__))
#os.path.dirname(__file__)でまずスクリプトの入っているディレクトリの名前を読み、そのディレクトリの絶対パスをos.path.abspath()で返している。

app.config['SQLALCHEMY_DATABASE_URI'] =\
    'sqlite:///' + os.path.join(basedir, 'data.sqlite')
app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

db = SQLAlchemy(app)

まあ、こうしておけば後で移動したときとかに安全なんだろうか。

tableの設定
リレーショナルデータベースの例として2つの関連性をもたせたtableを作る。

class Role(db.Model):
    __tablename__ = 'roles'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64), unique=True)
#このrolesテーブルにはカラムが2つ(整数のidと文字列のname)
#idはprimary keyに設定nameは重複がないように
    users = db.relationship('User', backref='role', lazy='dynamic')
#あとで説明
    def __repr__(self):
        return '<Role %r>' % self.name
#この部分はdebugに使うが、必須ではない。

class User(db.Model):
    __tablename__ = 'users'
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(64), unique=True, index=True)
    role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))

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

#    users = db.relationship('User', backref='role', lazy='dynamic')
#    role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))
#この2行でリレーションを作っている
#rolesテーブルのidの値を使ってusersテーブルのrole_idを表しているということ


設定がすべて出来上がったらまずデータベースを準備する。これは普通にSQLiteのデータベースをコマンド操作で作る作業でありflaskとはあんまり関係がない部分だな。

(venv3) $ python hello.py shell
>>> from hello import db
>>> db.create_all()
>>> from hello import Role, User
>>> admin_role = Role(name='Admin')
>>> mod_role = Role(name='Moderator')
>>> user_role = Role(name='User')
#Roleクラスにnameというカラムを用意し、3種類のnameを割り当てた
>>> user_john = User(username='john', role=admin_role)
>>> user_susan = User(username='susan', role=user_role)
>>> user_david = User(username='david', role=user_role)
#各userにusernameとroleを割り当て
>>> print(admin_role.id)
None
>>> print(mod_role.id)
None
>>> print(user_role.id)
None
#この時点では各roleにidはついていない
>>> db.session.add(admin_role)
>>> db.session.add(mod_role)
>>> db.session.add(user_role)
>>> db.session.add(user_john)
>>> db.session.add(user_susan)
>>> db.session.add(user_david)
>>> db.session.commit()
#データベース編集の確定
>>> print(admin_role.id)
1
>>> print(mod_role.id)
2
>>> print(user_role.id)
3
#roleにidが割り振られた
>>> print(user_role.name)
User
#user_roleのnameはUser
>>> print(user_john.id)
1
>>> print(user_susan.id)
2
#userにidが割り振られた
>>> print(user_susan.username)
susan
#user_susanのusernameはsusan
>>> print(user_susan.role_id)
3
#user_susanのrole_idはRoleのid=3に当たる

これでUserテーブル(id、username、role_id)とRoleテーブル(id、name)が出来上がりUserのrole_idとRoleのidでリレーションができていることになる。


このデータベースを作る部分はflaskからはできないみたい(テーブルの準備まではshellコマンドでやっとく必要がある)。
そこがちょっと面倒だな。