繁体   English   中英

如何使用mongokit / pymongo填充wtform select字段?

[英]How to populate wtform select field using mongokit/pymongo?

我正在尝试使用mongodb查询创建SelectField,但是到目前为止,我还没有成功:

# forms.py in blueprint
CATEGORIES = []
for item in db.Terms.find():
    CATEGORIES.append((item['slug'], item['name']))


class TermForm(Form):
    category = SelectField(
        choices=CATEGORIES,
        validators=[Optional()])

但我有一个例外:

Traceback (most recent call last):
  File "/home/one/Projects/proj/manage.py", line 14, in <module>
    app = create_app(os.getenv('FLASK_CONFIG') or 'default')
  File "/home/one/Projects/proj/app/__init__.py", line 27, in create_app
    from app.term.models import Term, TermCategory
  File "/home/one/Projects/proj/app/term/__init__.py", line 5, in <module>
    from . import views
  File "/home/one/Projects/proj/app/term/views.py", line 7, in <module>
    from .forms import TermForm, CategoryForm
  File "/home/one/Projects/proj/app/term/forms.py", line 48, in <module>
    for item in db.Terms.find():
  File "/home/one/.venv/proj/lib/python3.4/site-packages/flask_mongokit.py", line 238, in __getattr__
    self.connect()
  File "/home/one/.venv/proj/lib/python3.4/site-packages/flask_mongokit.py", line 196, in connect
    host=ctx.app.config.get('MONGODB_HOST'),
AttributeError: 'NoneType' object has no attribute 'app'

如果有人能进一步阐明这个话题,我将非常感激。

似乎您正在调用需要应用程序上下文( db.Terms.find )且没有可用上下文的方法。 您可以改为在视图中填充选择:

# 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()]

请参阅此答案的底部以获取您真正想要的内容,这第一部分只是为了解释您所遇到的立即错误。


您正在运行的代码依赖于此类上下文之外的应用程序上下文。 您需要运行在应用程序上下文中填充CATEGORIES的代码,以便Flask-MongoKit db可以获取连接。

似乎您正在使用应用程序工厂,因此请稍微重构代码,以便在创建应用程序时可以填充集合(您需要访问该应用程序以设置上下文)。

将代码放入函数中,然后在上下文中在工厂中导入并调用该函数。

# 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()
    #...

如果您使用的是蓝图,则可以添加一个在注册蓝图时执行的功能,因此应用程序工厂无需了解所有详细信息。 将所有导入(例如views移动到此注册功能内。 不需要上面的更改。

# 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

但是,在这种情况下,这些可能都不是您真正想要的。 似乎您正在尝试将表单字段的选择动态设置为数据库中的当前值。 如果您像现在一样执行此操作,则它将在应用程序启动时填充一次,然后即使数据库条目发生更改也不会更改。 真正想要做的是在表单的__init__方法中设置选择。

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)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM