2018-12-07

FlaskでWebアプリを作るときの忘備録

FlaskでWebアプリを作っているので、今後使いそうなところの忘備録

## flask-login


主な機能

  • login/logoutが login_user(user)/logout_user()で簡単に管理できる
  • ログインが必要なページを @login_requiredデコレーターで簡単に管理できる
  • グローバル変数current_userがスクリプトからもテンプレートからも使える
  • ログインしてない時はcurrent_userにAnonymousUserMixinオブジェクトがセットされ、いい感じに使える
    • is_active, is_authenticated == False
    • is_anonymous == True
    • get_id() returns None

## SQLAlchemy


  • Railsでいうrake db:migrateみたいな感じで、マイグレーション管理ができるパッケージ
  • flask db init -> DBの初期化
  • flask db migrate -> マイグレーションファイルの作成
  • flask db upgrade -> マイグレーションファイルの実行
  • flask db downgrade -> ロールバック

## One to One, One to Manyのリレーション


  • One to Manyのリレーションは下記コードの通り


class Person(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(50), nullable=False)
    addresses = db.relationship('Address', backref='person', lazy=True)

class Address(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    email = db.Column(db.String(120), nullable=False)
    person_id = db.Column(db.Integer, db.ForeignKey('person.id'),
        nullable=False)

  • One to Oneのリレーションは下記コードの通り
    • modelsの外部にForeignKey指定でユーザーIDを指定してあげる
    • 引用元はflask mega tutorial


app/models.py: Followers association table
followers = db.Table('followers',
    db.Column('follower_id', db.Integer, db.ForeignKey('user.id')),
    db.Column('followed_id', db.Integer, db.ForeignKey('user.id'))
)

  • ユーザーモデルの中に、以下のように書いてあげる。


class User(UserMixin, db.Model):
    # ...
    followed = db.relationship(
        'User', secondary=followers,
        primaryjoin=(followers.c.follower_id == id),
        secondaryjoin=(followers.c.followed_id == id),
        backref=db.backref('followers', lazy='dynamic'), lazy='dynamic')

  • フォローするなら、こんな感じ。


class User(UserMixin, db.Model):
    #...

    def follow(self, user):
        if not self.is_following(user):
            self.followed.append(user)

    def unfollow(self, user):
        if self.is_following(user):
            self.followed.remove(user)

    def is_following(self, user):
        return self.followed.filter(
            followers.c.followed_id == user.id).count() > 0

routingしてあげるときはこんな感じ。

app/routes.py: Follow and unfollow routes.
@app.route('/follow/<username>')
@login_required
def follow(username):
    user = User.query.filter_by(username=username).first()
    if user is None:
        flash('User {} not found.'.format(username))
        return redirect(url_for('index'))
    if user == current_user:
        flash('You cannot follow yourself!')
        return redirect(url_for('user', username=username))
    current_user.follow(user)
    db.session.commit()
    flash('You are following {}!'.format(username))
    return redirect(url_for('user', username=username))

@app.route('/unfollow/<username>')
@login_required
def unfollow(username):
    user = User.query.filter_by(username=username).first()
    if user is None:
        flash('User {} not found.'.format(username))
        return redirect(url_for('index'))
    if user == current_user:
        flash('You cannot unfollow yourself!')
        return redirect(url_for('user', username=username))
    current_user.unfollow(user)
    db.session.commit()
    flash('You are not following {}.'.format(username))
    return redirect(url_for('user', username=username))




参考

注目の投稿

めちゃくちゃ久しぶりにこのブログ書いたw 更新3年ぶりw > 多様性というゲームは尊厳と自由を勝ち取るゲームなのかもしれないな。  もともとツイッターでツイートした内容なんだけど、ちょっと深ぼる。 ----- 自分は男 x 30代x 二児の父 x 経営者 x 都心(共働き世...