Reputation: 980
I am attempting to create a simple webapp using Python3.4, Flask, and MongoEngine.
I am having a problem when attempting to create a form using WTForms.
I have an initialized MongoEngine application called database:
database = MongoEngine(app)
I created a model class called 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)
I have a route to create a form using this class:
@app.route('/blog/new')
def new():
form = model_form(Post)
return render_template('new_blog.html', form=form)
When I run this route, I get a TypeError:
TypeError: model must be a mongoengine Document schema
Looking in the WTForm code, it seems to require the Post class to be an instance of MongoEngine's BaseDocument
or DocumentMetaclass classes
. Lines 223-224 of /usr/local/lib/python3.4/dist-packages/flask_mongoengine/wtf/orm.py
read:
from mongoengine.base import BaseDocument, DocumentMetaclass
if not isinstance(model, (BaseDocument, DocumentMetaclass)):
raise TypeError('model must be a mongoengine Document schema'
When I attempt to manually check my Post class, it seems to be a DocumentMetaclass
, but not a BaseDocument
. Adding
app.logger.debug(isinstance(Post, mongoengine.base.BaseDocument))
app.logger.debug(isinstance(Post, mongoengine.base.DocumentMetaclass))
to my code returns:
--------------------------------------------------------------------------------
DEBUG in __init__ [__init__.py:57]:
False
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
DEBUG in __init__ [__init__.py:58]:
True
--------------------------------------------------------------------------------
What am I doing wrong?
The full text of my __init__.py
file is:
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)
Upvotes: 2
Views: 732
Reputation: 832
I find the same problem.
When I printed all local variables before exception I finded that current model is satisfy condition
if not isinstance(model, (BaseDocument, DocumentMetaclass)):
but the next will not. The next model was path to related model. In you example that is database.EmbeddedDocumentField('Comment')
The exception raised when list property ListField defined with string path to listed model
comments = database.ListField(
database.EmbeddedDocumentField('Comment')
)
instead define with model class
comments = database.ListField(
database.EmbeddedDocumentField(Comment)
)
I solve this bug in my pull-request in Flask-Admin project. https://github.com/mrjoes/flask-admin/pull/645
Upvotes: 1
Reputation: 729
Are you importing the database instance with which you initialized the app?
Here's an example of what a models.py might look like. It seems to me as though your program doesn't know what you mean when you're writing database.Document
, so I suspect this is your issue:
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()
Upvotes: 0