kuroの覚え書き

96の個人的覚え書き

__init__.pyってなんだ?

基本はpythonスクリプトがあるディレクトリを表すもので、中身は空でいいようだ。
つまり、メインのスクリプトがmanage.pyだとして

-+-manage.py
 |
 +-app-+-__init__.py
      |
      +-models.py

というような構成になっているとappフォルダにはスクリプトが入っているよという目印になる。こうなっているとmanage.pyにmodels.pyをモジュールとしてインポートするには

import app.models.py

もしくは

from app import models.py

とすると良くなる。

models.pyで定義したdbをインポートするなら

from app.models  import db

なのだね。

さらにこの__init__.pyの中に

from flask import Flask
app = Flask(__name__)

app.config['DEBUG'] = True
app.config['SECRET_KEY'] = 'hard to guess string'

app.config['SQLALCHEMY_DATABASE_URI'] =\
    'mysql+pymysql://root:password@localhost/flaskdata'
app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

と定義しておくとmanage.pyは

from app import app

を追加しておくだけで、上のapp = Flask(__name__)からapp.configまでを取り除ける。
なおその際、templatesフォルダもappフォルダの中に移動となる。

さらにさらに
この__init__.pyを

from flask import Flask
app = Flask(__name__)

app.config.from_object('app.config')

とだけにしてやって、新たにconfig.pyを同じ階層に作り

DEBUG = True
SECRET_KEY = 'hard to guess string'
SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://root:password@localhost/flaskdata'
SQLALCHEMY_COMMIT_ON_TEARDOWN = True
SQLALCHEMY_TRACK_MODIFICATIONS = False

としておくとこのconfigファイルから読み込んで同じ動作が可能。
なおapp.config.from_objectで読み取る場合変数名は大文字にしておく必要がある。

だいぶわかってきたぞ。
__init__.py

from flask import Flask
app = Flask(__name__)
app.config.from_object('app.config')
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy(app)
from flask_bootstrap import Bootstrap
bootstrap = Bootstrap(app)
from flask_moment import Moment
moment = Moment(app)
from flask_script import Manager
manager = Manager(app)

とdbとbootstrapとMomentもこちらに移して、manage.pyから該当する部分を削除
models.pyからも

from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()

を削除し、かわりに

from app import db

を入れておく。

最終的にはmanage.pyには

from app import app, db

from flask_script import Manager, Shell
from flask_migrate import Migrate, MigrateCommand
from app.models import User, Role
migrate = Migrate(app, db)

def make_shell_context():
    return dict(app=app, db=db, User=User, Role=Role)
manager.add_command("shell", Shell(make_context=make_shell_context))
manager.add_command("db", MigrateCommand)

if __name__ == '__main__':
    manager.run()

だけが残り、view.pyに、描画関係の残り全部が移動する。

from flask import render_template, session, redirect, url_for

from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField
from wtforms.validators import Required

from app.models import User, Role
from app import app, db, moment, manager

class NameForm(FlaskForm):
    name = StringField('What is your name?', validators=[Required()])
    submit = SubmitField('Submit')

@app.errorhandler(404)
def page_not_found(e):
    return render_template('404.html'), 404


@app.errorhandler(500)
def internal_server_error(e):
    return render_template('500.html'), 500


@app.route('/', methods=['GET', 'POST'])
def index():
    form = NameForm()
    if form.validate_on_submit():
        user = User.query.filter_by(username=form.name.data).first()
        if user is None:
            user = User(username=form.name.data)
            db.session.add(user)
            session['known'] = False
        else:
            session['known'] = True
        session['name'] = form.name.data
        return redirect(url_for('index'))
    return render_template('index.html', form=form, name=session.get('name'),
                           known=session.get('known', False))

これで一応のファイル分割はできたことになるが、どうやらBlueprintなる機能があるらしく、それを使うととても便利らしい。
あとformも別ファイルにしてやったほうがスッキリするかもしれない。
現在のファイル構成

-+-manage.py
 |
 +-app-+-__init__.py
      |
      +-config.py
      |
      +-models.py
      |
      +-view.py
      |
      +-template-+-base.html
                 |
                 +-index.html

ここまで結構時間がかかったが、ここからデータベース本体の取扱を中心に進めていくことになるだろう(多分)