【问题标题】:TypeError When Creating a WTForm with MongoEngine and Flask使用 MongoEngine 和 Flask 创建 WTForm 时出现 TypeError
【发布时间】:2014-08-25 17:35:32
【问题描述】:

我正在尝试使用 Python3.4、Flask 和 MongoEngine 创建一个简单的 web 应用程序。

我在尝试使用 WTForms 创建表单时遇到问题。

我有一个名为数据库的初始化 MongoEngine 应用程序:

database = MongoEngine(app)

我创建了一个名为 Post 的模型类:

class Post(database.Document):
    author = database.StringField(
        default='David Y. Stephenson', max_length=255, required=True
    )
    body = database.StringField(required=True)
    comments = database.ListField(
        database.EmbeddedDocumentField('Comment')
    )
    slug = database.StringField(max_length=255, required=True, unique=True)
    tease = database.StringField(max_length=255, required=True)
    time = database.DateTimeField(
        default=datetime.datetime.now, required=True
    )
    title = database.StringField(max_length=255, required=True, unique=True)

我有一个使用此类创建表单的路线:

@app.route('/blog/new')
def new():
    form = model_form(Post)
    return render_template('new_blog.html', form=form)

当我运行这条路线时,我得到一个 TypeError:

TypeError: model must be a mongoengine Document schema

查看 WTForm 代码,似乎要求 Post 类是 MongoEngine 的 BaseDocumentDocumentMetaclass classes 的实例。 /usr/local/lib/python3.4/dist-packages/flask_mongoengine/wtf/orm.py 的第 223-224 行阅读:

from mongoengine.base import BaseDocument, DocumentMetaclass
if not isinstance(model, (BaseDocument, DocumentMetaclass)):
    raise TypeError('model must be a mongoengine Document schema'

当我尝试手动检查我的 Post 类时,它似乎是 DocumentMetaclass,而不是 BaseDocument。添加

app.logger.debug(isinstance(Post, mongoengine.base.BaseDocument))
app.logger.debug(isinstance(Post, mongoengine.base.DocumentMetaclass))

我的代码返回:

--------------------------------------------------------------------------------
DEBUG in __init__ [__init__.py:57]:
False
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
DEBUG in __init__ [__init__.py:58]:
True
--------------------------------------------------------------------------------

我做错了什么?

我的__init__.py文件全文为:

import datetime
from flask import Flask
from flask import render_template
from flask.ext.mongoengine import MongoEngine
from flask.ext.mongoengine.wtf import model_form
import mongoengine.base


app = Flask(__name__)


app.config['MONGODB_SETTINGS'] = {
    'db': 'davidystephenson',
    'host': 'ds059908.mongolab.com',
    'username': 'david',
    'password': 'opensecret',
    'port': 59908,
}
database = MongoEngine(app)


class Post(database.Document):
    author = database.StringField(
        default='David Y. Stephenson', max_length=255, required=True
    )
    body = database.StringField(required=True)
    comments = database.ListField(
        database.EmbeddedDocumentField('Comment')
    )
    slug = database.StringField(max_length=255, required=True, unique=True)
    tease = database.StringField(max_length=255, required=True)
    time = database.DateTimeField(
        default=datetime.datetime.now, required=True
    )
    title = database.StringField(max_length=255, required=True, unique=True)


@app.route('/')
def index():
    return render_template('index.html')


@app.route('/blog/')
def blog():
    posts = Post.objects.all()
    return render_template('blog.html', posts=posts)


@app.route('/blog/<slug>')
def post(slug):
    post = Post.objects.get(slug=slug)
    return render_template('post.html', post=post)


@app.route('/blog/new')
def new():
    app.logger.debug(isinstance(Post, mongoengine.base.BaseDocument))
    app.logger.debug(isinstance(Post, mongoengine.base.DocumentMetaclass))
    form = model_form(Post)
    return render_template('new_blog.html', form=form)

if __name__ == '__main__':
    app.run(debug=True)

【问题讨论】:

    标签: python-3.x flask mongoengine wtforms flask-mongoengine


    【解决方案1】:

    我发现了同样的问题。

    当我在异常之前打印所有局部变量时,我发现当前模型满足条件

    if not isinstance(model, (BaseDocument, DocumentMetaclass)):
    

    但下一个不会。下一个模型是相关模型的路径。在你的例子中是 database.EmbeddedDocumentField('Comment')

    使用列出模型的字符串路径定义列表属性 ListField 时引发的异常

    comments = database.ListField(
        database.EmbeddedDocumentField('Comment')
    )
    

    而是用模型类定义

    comments = database.ListField(
        database.EmbeddedDocumentField(Comment)
    )
    

    我在 Flask-Admin 项目的拉取请求中解决了这个错误。 https://github.com/mrjoes/flask-admin/pull/645

    【讨论】:

    • 我认为这是 Flask-Admin 中的一个错误,但是您可以通过导入 Comment 模型并将其设置为类 database.EmbeddedDocumentField(Comment) 来解决您的问题。昨天我创建了问题github.com/mrjoes/flask-admin/issues/636
    【解决方案2】:

    您是否正在导入初始化应用程序的数据库实例?

    下面是一个models.py 的示例。在我看来,当你写database.Document 时,你的程序似乎不知道你的意思,所以我怀疑这是你的问题:

    from app import db # <- Do you have this line in the same file as your class?
    
    class Person(db.DynamicDocument):
    
        # Meta variables.
        meta = {
            'collection': 'people'
        }
    
    # Document variables.
    age = db.IntField()
    name = db.StringField()
    

    【讨论】:

    • 当然,db.Document 和 db.DynamicDocument 都应该可以正常工作。可以这么说,它们只是同一主题的变体。
    • 是的,我有。我什至尝试将 Post 类移动到 init.py 以尝试解决此问题。我将 init.py 的全文添加到我的问题中。
    • 有趣。在这种情况下,我没有一个直接的答案给你,而是一种方法——我建议首先创建这个应用程序的一个大大简化的版本,只是为了让基础工作正常。然后,如果您访问一个网页并且它仍然中断并提供堆栈跟踪,我将使用控制台(在调试器页面中提供)调查每个阶段的对象以查看发生了什么。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-07-27
    • 2015-06-08
    • 2015-06-13
    • 1970-01-01
    • 1970-01-01
    • 2019-02-09
    • 1970-01-01
    相关资源
    最近更新 更多