web-dev-qa-db-ja.com

Flask管理者はフォームの値を覚えています

私のアプリケーションでは、モデルとしてユーザーと投稿があります。各投稿には、ユーザー名への外部キーがあります。投稿モデルの上にModelViewを作成すると、以下のスクリーンショットに示すように、管理インターフェイスで特定のユーザーとして投稿を作成できます

enter image description here

投稿を追加して[保存して別のものを追加]をクリックすると、[ユーザー]が[ユーザー1]に戻ります。フォームに以前の値「user2」を記憶させるにはどうすればよいですか?

私の研究により、on_model_changeとon_form_prefillを変更し、以前の値をflaskセッションに保存することでそれを行うことができると信じていますが、そのような単純なタスクは過度に設計されているようです。より簡単な方法。

私のコードは以下にあります

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
import flask_admin
from flask_admin.contrib import sqla

app = Flask(__name__)

db = SQLAlchemy()

admin = flask_admin.Admin(name='Test')


class Users(db.Model):
    """
    Contains users of the database
    """
    user_id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(64), index=True, unique=True, nullable=False)

    def __str__(self):
        return self.username


class Posts(db.Model):
    """
    Contains users of the database
    """
    post_id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(11), db.ForeignKey(Users.username), nullable=False)
    post = db.Column(db.String(256))
    user = db.relation(Users, backref='user')


def build_sample_db():
    db.drop_all()
    db.create_all()
    data = {'user1': 'post1', 'user1': 'post2', 'user2': 'post1'}
    for user, post in data.items():

        u = Users(username=user)
        p = Posts(username=user, post=post)

        db.session.add(u)
        db.session.add(p)
    db.session.commit()

class MyModelView(sqla.ModelView):

    pass


if __name__ == '__main__':

    app.config['SECRET_KEY'] = '123456790'
    app.config['DATABASE_FILE'] = 'sample_db.sqlite'
    app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///database'
    app.config['SQLALCHEMY_ECHO'] = True
    db.init_app(app)

    admin.init_app(app)
    admin.add_view(MyModelView(Posts, db.session))

    with app.app_context():
        build_sample_db()

    # Start app
    app.run(debug=True)

12
user787267

on_form_prefillは編集フォームでのみ機能するため、この問題の解決にはなりません。

Libコードが言うように-> on_form_prefill =>編集フォームを事前入力するために追加のアクションを実行します

リクエストがヒットすると、以下のコードフローが発生します。

(基本クラス)View(create_view)-> create_form-> _ create_form_class-> get_create_form-> get_form-> scaffold_form

したがって、ロードされる作成フォームのデフォルト値を変更したい場合は、上記のフローで説明したように、フォームを処理するメソッドでそれを更新できます。

したがって、create_formをオーバーライドできます。

 def create_form(self):
     form = super().create_form()
     # set the user id we want in the form as default.
     form.user_id.default = 'USER_2_ID'
     return form

これは、フォームのデフォルト値getでした。

To set on_model_changeをオーバーライドする値

def on_model_change(self, form, model, is_created):
    # set the USER_ID from this model.user_id
    pass

これで、setterおよびgetterメソッドからこのデータ(USER_ID)を共有する方法は次のとおりです。

  1. これをCookieに設定し、作成リクエストを取得します。
  2. 「保存してもう1つ追加」ボタンのリンクを更新して、クエリ文字列にuser_idを追加します。

このデータは2つの異なるリクエスト間で共有する必要があるため、アプリケーションコンテキストに保存すると機能しません。アプリケーションコンテキストは「要求間で共有されません」

 def create_form(self):
     form = super().create_form()
     user_id = request.args.get('user_id')
     form.user_id.default = user_id

     # or if you want only one option to be available 
     user_query = self.session.query(User).filter(User.id = user_id).one()
     form.user.query = [user_query]
     return form

上記の回答のように、edit_view、create_viewを使用することについて言及しています。

簡単なオプションですが、最後のエントリが得られるように作成をクエリするのは良い方法ではありません(しかし、このアプローチは最適ではありません

@expose('/new/', methods=('GET', 'POST'))
def create_view(self):
    model = self.get_model()
    # query the model here to get the latest value of the user_id
    self._template_args['user_id'] = user_id
    return super(YourAdmin, self).details_view()
0
abhishek kasana