Sqlalchemy 为什么Flask管理员在尝试编辑模型时会引发此异常?

Sqlalchemy 为什么Flask管理员在尝试编辑模型时会引发此异常?,sqlalchemy,flask-sqlalchemy,wtforms,flask-wtforms,flask-admin,Sqlalchemy,Flask Sqlalchemy,Wtforms,Flask Wtforms,Flask Admin,例外情况是AttributeError:“StringField”对象没有属性“wrap\u formdata”,似乎只有在我从Flask管理仪表板创建或编辑以下两个模型时才会发生这种情况: class Experiment(db.Model): id = db.Column(db.Integer, primary_key=True) property_id = db.Column(db.Integer, db.Forei

例外情况是
AttributeError:“StringField”对象没有属性“wrap\u formdata”
,似乎只有在我从Flask管理仪表板创建或编辑以下两个模型时才会发生这种情况:

class Experiment(db.Model):
    id = db.Column(db.Integer, primary_key=True)

    property_id = db.Column(db.Integer,
                            db.ForeignKey('property.id'),
                            index=True,
                            nullable=False)

    name = db.Column(db.String, nullable=False)

    start_date = db.Column(db.DateTime, nullable=True)
    end_date = db.Column(db.DateTime, nullable=True)
    status = db.Column(db.String, nullable=False, default='Draft')

    title = db.Column(db.String)
    meta = db.Column(db.String)
    seed_uri = db.Column(db.String)

    targets = db.Column(postgresql.JSON)
    variations_json = db.Column(postgresql.JSON)

    variations = db.relationship('ExperimentVariation',
                                  backref='experiment',
                                  cascade='save-update, merge, delete')

    def __repr__(self):
        repr_fmt = '<Experiment {id}, {property_id} {name}>'
        return repr_fmt.format(id=self.id,
                               property_id=self.property_id,
                               name=self.name)


class ExperimentVariation(db.Model):
    id = db.Column(db.Integer, primary_key=True)

    experiment_id = db.Column(db.Integer,
                              db.ForeignKey('experiment.id'),
                              index=True,
                              nullable=False)

    name = db.Column(db.String, nullable=False)

    title = db.Column(db.String)
    meta = db.Column(db.String)

    def __repr__(self):
        repr_fmt = '<ExperimentVariation {id}, {experiment_id} {name}>'
        return repr_fmt.format(id=self.id,
                               experiment_id=self.experiment_id,
                               name=self.name)

我已经找出了这个问题的根本原因:Flask Admin从每个SQLA模型构造了一个表单类,默认情况下它是WTForm表单类的子类。这一切都很好,除非您的一列与WTForm的构造函数采用的参数之一匹配,例如
meta

构建所述类的逻辑是。我不完全确定什么是正确的修复方法,但是这似乎是一个管理员需要在技术上或社会上处理的情况。例如,提前知道
meta
不应该用作列名是很方便的,因为这样会出现问题

值得指出的是,WTForm的表单构造函数也接受以下变量,因此可能也应该避免使用这些变量:
formdata
obj
prefix
data


这个问题的一个技术解决方案可能是构造一组变量名,然后在上面的Flask管理代码中创建模型表单时显式检查它们。然后可以生成某种类型的警告,或者可以更改
名称
变量,使其前缀为
\uu
或类似的内容。这不是一个完美的解决方案,因为WTForms将来可能会更改其API。

我已经将其缩小到名为
meta
的列中:这个值似乎与WTForms关心的其他值一起被屏蔽了。不太清楚这是在哪里发生的。一旦我找到了,我会更新的。我最初的感觉是这应该在flask admin/wtforms中修复。
ERROR [ranksci] Exception on /admin/experiment/edit/ [GET]
Traceback (most recent call last):
  File "/Users/max/Documents/projects/ranksci-app/virtualenv/lib/python2.7/site-packages/flask/app.py", line 1988, in wsgi_app
    response = self.full_dispatch_request()
  File "/Users/max/Documents/projects/ranksci-app/virtualenv/lib/python2.7/site-packages/flask/app.py", line 1641, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/Users/max/Documents/projects/ranksci-app/virtualenv/lib/python2.7/site-packages/flask/app.py", line 1544, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "/Users/max/Documents/projects/ranksci-app/virtualenv/lib/python2.7/site-packages/flask/app.py", line 1639, in full_dispatch_request
    rv = self.dispatch_request()
  File "/Users/max/Documents/projects/ranksci-app/virtualenv/lib/python2.7/site-packages/flask/app.py", line 1625, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/Users/max/Documents/projects/ranksci-app/virtualenv/lib/python2.7/site-packages/flask_admin/base.py", line 69, in inner
    return self._run_view(f, *args, **kwargs)
  File "/Users/max/Documents/projects/ranksci-app/virtualenv/lib/python2.7/site-packages/flask_admin/base.py", line 368, in _run_view
    return fn(self, *args, **kwargs)
  File "/Users/max/Documents/projects/ranksci-app/virtualenv/lib/python2.7/site-packages/flask_admin/model/base.py", line 1969, in edit_view
    form = self.edit_form(obj=model)
  File "/Users/max/Documents/projects/ranksci-app/virtualenv/lib/python2.7/site-packages/flask_admin/model/base.py", line 1256, in edit_form
    return self._edit_form_class(get_form_data(), obj=obj)
  File "/Users/max/Documents/projects/ranksci-app/virtualenv/lib/python2.7/site-packages/wtforms/form.py", line 212, in __call__
    return type.__call__(cls, *args, **kwargs)
  File "/Users/max/Documents/projects/ranksci-app/virtualenv/lib/python2.7/site-packages/flask_admin/form/__init__.py", line 16, in __init__
    super(BaseForm, self).__init__(formdata=formdata, obj=obj, prefix=prefix, **kwargs)
  File "/Users/max/Documents/projects/ranksci-app/virtualenv/lib/python2.7/site-packages/wtforms/form.py", line 278, in __init__
    self.process(formdata, obj, data=data, **kwargs)
  File "/Users/max/Documents/projects/ranksci-app/virtualenv/lib/python2.7/site-packages/wtforms/form.py", line 119, in process
    formdata = self.meta.wrap_formdata(self, formdata)
AttributeError: 'StringField' object has no attribute 'wrap_formdata'