如何使用 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()]
请参阅此答案的底部了解您真正想要的内容,第一部分只是解释您遇到的即时错误。
您 运行ning 代码依赖于此类上下文之外的应用程序上下文。您需要 运行 在应用程序上下文中填充 CATEGORIES
的代码,以便 Flask-MongoKit 数据库可以获得连接。
看起来您正在使用应用程序工厂,因此请稍微重构您的代码,以便您可以在创建应用程序时填充集合(您需要访问该应用程序才能设置上下文)。
将代码放入函数中,然后在上下文中的工厂中导入并调用该函数。
# 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)
我正在尝试使用 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()]
请参阅此答案的底部了解您真正想要的内容,第一部分只是解释您遇到的即时错误。
您 运行ning 代码依赖于此类上下文之外的应用程序上下文。您需要 运行 在应用程序上下文中填充 CATEGORIES
的代码,以便 Flask-MongoKit 数据库可以获得连接。
看起来您正在使用应用程序工厂,因此请稍微重构您的代码,以便您可以在创建应用程序时填充集合(您需要访问该应用程序才能设置上下文)。
将代码放入函数中,然后在上下文中的工厂中导入并调用该函数。
# 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)