【问题标题】:Flask admin remember form value烧瓶管理员记住表单值
【发布时间】:2019-07-17 07:53:00
【问题描述】:

在我的应用程序中,我有用户和帖子作为模型。每个帖子都有一个用户名的外键。当我在我的 Posts 模型上创建 ModelView 时,我可以在管理界面中以特定用户的身份创建帖子 如下图所示

添加帖子并单击“保存并添加另一个”后,“用户”恢复为“用户1”。如何让表单记住以前的值“user2”?

我的研究让我相信可以通过修改 on_model_change 和 on_form_prefill 并在烧瓶会话中保存以前的值来完成,但它似乎过度设计了这样一个简单的任务。一定有更简单的方法。

我的代码如下所示

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)

【问题讨论】:

  • [保存并添加另一个]表示清除当前表格并填写新表格。如果您想在选择框中使用以前的表单用户作为默认值,您可以使用 cookie(client) 或 session(server) 来保存用户值并实现它。
  • 我不认为您从研究中得到的解决方案是过度设计的。正如@John 所说,您必须维护 cookie 或会话才能使其成为可能。
  • 如果我误解了您的问题,请原谅我@user787267,但是您是否有兴趣将表单的默认加载选项更改为当前选择的内容,或者动态添加用户并将其设置为默认值表格?
  • @calestini 我有兴趣让表单记住用户最后选择的值。因此,如果管理员想要为 user2 添加多个帖子,他不必在每次插入时重新选择 user2。
  • @user787267,总体选项将是 (1) 异步发送表单以便当前值保持预加载,(2) 如上所述的 cookie,(3) 传递 url 参数,例如 @ 987654324@ 并动态更改表单上的默认值,或 (4) 保存会话。选项 3 是一种简单、笨拙的方式,但它会在 url 上公开您的内部 id。

标签: python flask flask-admin


【解决方案1】:

我以前遇到过这种情况,我已经使用 2 个函数解决了它。它非常容易和小。

@expose('/edit/', methods=('GET', 'POST'))
def edit_view(self):
    #write your logic to populate the value into html        
    self._template_args["arg_name"] = stored_value
    # in your html find this value to populate it as you need

当用户尝试编辑任何值时,上述函数将允许您在 html 中填充值。这可以使用存储的值来填充。下面是一个功能,可以帮助您保存以前编辑的值。

class MyModelView(sqla.ModelView): 中,您需要添加以下 2 个函数。

def on_model_change(self, form, model, is_created):
    stored_value = model.user # this is your user name stored
    # get the value of the column from your model and save it 

这是一个两步操作,非常小,不需要很多时间。我现在只添加了一个骨架/伪代码。

【讨论】:

  • 谢谢!如果您能添加剩余的代码,我将不胜感激
【解决方案2】:

on_form_prefill 不会帮助您解决这个问题,因为它只适用于编辑表单。

正如 lib 代码所说 -> on_form_prefill => 执行附加操作以 预填编辑表单

当请求命中时,会发生以下代码流:

(基类)视图(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

这是为了获取表单的默认值。

设置我们覆盖 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. 更新“保存并添加另一个”按钮链接以在查询字符串中添加 user_id。

此数据必须在两个不同的请求之间共享,因此将其存储在应用程序上下文中,g 将不起作用。应用程序上下文“不会在请求之间共享”

 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()

【讨论】:

  • 这也是一个很好的答案!我从来没有设法让它与_template_args一起工作,但设置if 'user_id' in flask.session and not form.case.data: form.case.data=db.session.query(models.Users).filter_by(user_id=flask.session['user_id']).first()我让它工作了。出于某种奇怪的原因,我不得不覆盖 form.case.data 而不是 form.case.default
猜你喜欢
  • 2018-04-15
  • 2023-04-05
  • 1970-01-01
  • 1970-01-01
  • 2020-08-11
  • 2015-09-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多