【问题标题】:Flask-admin: catch changes on inline_modelsFlask-admin:捕捉 inline_models 的变化
【发布时间】:2015-10-07 21:04:36
【问题描述】:

我有一个简单的应用程序,提供了完整的代码here。它使用烧瓶管理

模型:

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String, unique=True)


class UserNote(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    body = db.Column(db.String, nullable=False)
    user_id = db.Column(db.Integer, db.ForeignKey('users.id'))
    author_id = db.Column(db.Integer, db.ForeignKey('users.id'))
    user = db.relationship(User,
                           foreign_keys='UserNote.user_id',
                           backref=db.backref('user_notes', order_by=id))
    author = db.relationship(User,
                             foreign_keys='UserNote.author_id',
                             backref=db.backref('author_user_notes',
                                                order_by=id))

和主app.py:

app = Flask(__name__)

class ModelFormWithAuthorship(InlineFormAdmin):
    def on_model_change(self, form, model):
        user = User.query.first()
        print('++++++')
        print(user)
        print(model)
        print('++++++')
        model.author = user

class UserModelView(ModelView):
    inline_models = (ModelFormWithAuthorship(UserNote),)


admin = Admin(app, url='/admin', name='MyAdmin', template_mode='bootstrap3')
admin.add_view(UserModelView(User, db.session))

我想自动将查询中的第一个用户设置为更改的 UserNote 的作者。这是对当前登录用户的简化。

但烧瓶管理员将所有内联模型传递给此方法。

这里是reorduce的步骤

  1. 开始申请
  2. 创建名为 user1 的用户(此用户可能是 first())
  3. 创建名为 admin1 的用户
  4. 创建名为 admin2 的用户
  5. 创建 2 个内联注释,它将 user1 作为作者
  6. 直接连接到数据库,将其中一个注释的作者更改为 admin1,将另一个注释的作者更改为 admin2
  7. 转到 Flask-Admin 并确保您有来自 2 个用户的 2 个注释
  8. 编辑第一条笔记的正文并点击保存

对我来说,这些操作的预期结果是,第一个注释将 user1 作为作者,第二个注释的作者将保持不变。 但实际结果如下:两个注释的作者都设置为 user1。

我试过调试,发现了一些有趣的属性:

# Not changed note
model._sa_instance_state._attached = {bool} True
model._sa_instance_state.deleted = {bool} False
model._sa_instance_state.detached = {bool} False
model._sa_instance_state.expired = {bool} False
model._sa_instance_state.has_identity = {bool} True
model._sa_instance_state.pending = {bool} False
model._sa_instance_state.persistent = {bool} True
model._sa_instance_state.transient = {bool} False
model.body = {str} 'test1'
model._sa_instance_state.modified = {bool} True

# Changed note
model._sa_instance_state._attached = {bool} True
model._sa_instance_state.deleted = {bool} False
model._sa_instance_state.detached = {bool} False
model._sa_instance_state.expired = {bool} False
model._sa_instance_state.has_identity = {bool} True
model._sa_instance_state.pending = {bool} False
model._sa_instance_state.persistent = {bool} True
model._sa_instance_state.transient = {bool} False
model.body = {str} 'test2A'
model._sa_instance_state.modified = {bool} True

但它们彼此没有区别。

有没有办法只捕获更改的模型?

【问题讨论】:

    标签: python flask flask-wtforms flask-admin


    【解决方案1】:

    您可以使用 WTForms 的Field.object_data 属性:

    这是从对象或 kwargs 传递到字段的数据, 存储未修改。这可以被模板、小部件、验证器使用 根据需要(例如用于比较)

    因此您可以比较UserNote.body 旧值和新值,然后根据需要更改作者,如下所示:

    class ModelFormWithAuthorship(InlineFormAdmin):
        def on_model_change(self, form, model):    
            # Check whether note's body has changed
            if form.body.object_data != form.body.data:
                model.author = User.query.first()
    

    【讨论】:

      猜你喜欢
      • 2022-10-24
      • 2020-11-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-04
      相关资源
      最近更新 更多