How to populate wtform select field using mongokit/pymongo?

大城市里の小女人 提交于 2019-11-28 13:05:41

See the bottom of this answer for what you really want, this first section is just to explain the immediate error you're getting.


You are running code that depends on an application context outside of such a context. You'll need to run the code that populates CATEGORIES inside an application context so that the Flask-MongoKit db can get a connection.

It looks like you're using an application factory, so refactor your code a bit so that you can populate the collection while creating the app (you need access to the app to set up a context).

Put the code inside a function, then import and call that function in the factory within a context.

# forms.py

CATEGORIES = []

def init():
    for item in db.Terms.find():
        CATEGORIES.append((item['slug'], item['name']))

# add to create_app function (even the import)

def create_app(conf):
    #...
    from app.term import forms

    with app.app_context():
        forms.init()
    #...

If you you're using blueprints, you can add a function that executes when the blueprint is registered, so the app factory doesn't need to know about all the details. Move all imports such as views to inside this registration function. The changes from above are not needed.

# at the bottom of app/term/__init__.py
# assuming blueprint is called bp

@bp.record_once
def register(state):
    with state.app.app_context():
        from . import forms, views

However, neither of these are probably what you actually want in this case. It looks like you're trying to dynamically set the choices for a form field to the current values in the database. If you do this as you are now, it will be populated once when the app starts and then never change even if the database entries change. What you really want to do is set the choices in the form's __init__ method.

class TestForm(Form):
    category = SelectField()

    def __init__(self, *args, **kwargs):
        self.category.kwargs['choices'] = [(item['slug'], item['name']) for item in db.Terms.find()]
        Form.__init__(self, *args, **kwargs)

It looks like you're calling a method that needs an app context (db.Terms.find) without having the context available. You can populate the choices in the view instead:

# forms.py
class TermForm(Form):
    category = SelectField(validators=[Optional()])


# views.py
form = TermForm()
form.category.choices = [(item['slug'], item['name']) for item in db.Terms.find()]
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!