【问题标题】:How to populate wtform select field using mongokit/pymongo?如何使用 mongokit/pymongo 填充 wtform 选择字段?
【发布时间】:2015-03-23 21:44:49
【问题描述】:

我正在尝试使用 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'

如果有人能对这个主题有更多的了解,我将不胜感激。

【问题讨论】:

    标签: python flask pymongo wtforms flask-wtforms


    【解决方案1】:

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


    您正在运行的代码依赖于此类上下文之外的应用程序上下文。您需要在应用程序上下文中运行填充 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)
    

    【讨论】:

      【解决方案2】:

      看起来您正在调用一个需要应用上下文 (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()]
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-09-28
        • 1970-01-01
        • 2016-05-10
        • 1970-01-01
        • 2017-05-05
        • 1970-01-01
        相关资源
        最近更新 更多