Flask-admin:捕获inline_models上的更改

时间:2015-10-07 21:04:36

标签: python flask flask-wtforms flask-admin

我有一个简单的应用程序,完整的代码显示here。它使用flask-admin

模特:

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的作者。它是当前登录用户的简化。

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

以下是重新制作的步骤

  1. 启动申请
  2. 创建名为user1的用户(此用户可能是第一个())
  3. 创建名为admin1的用户
  4. 创建名为admin2的用户
  5. 创建2个内联注释,它将user1作为作者
  6. 直接连接数据库并将其中一个注释的作者更改为admin1,另一个注释更改为admin2
  7. 转到Flask-Admin并确保您有2个用户的2个备注
  8. 修改第一个备注的正文,然后点击保存
  9. 对我来说,这些操作的

    预期结果是,第一个音符会将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
    

    但是他们彼此无法区分。

    有没有办法只捕捉改变过的模型?

1 个答案:

答案 0 :(得分:4)

您可以使用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()