【问题标题】:Use WTForms QuerySelectField with Pyramid 1.7's db session将 WTForms QuerySelectField 与 Pyramid 1.7 的数据库会话一起使用
【发布时间】:2016-08-27 02:54:08
【问题描述】:

我在我的金字塔应用程序中使用 wtforms_sqlalchemy 并定义了几个 QuerySelectFields。查询工厂使用导入的DBSession 对象进行查询。

from wtforms.form import Form
from wtforms_sqlalchemy.fields import QuerySelectField
from myapp.models import DBSession, MyModel

def mymodel_choices():
    choices = DBSession.query(MyModel)
    return choices

class MyForm(Form):
    mymod = QuerySelectField(u'Field', query_factory=mymodel_choices)

Pyramid 1.7 引入了一个新的 SQLAlchemy 脚手架,它将 db 会话对象附加到每个请求。在我看来,使用新的脚手架mymodel_choices 必须使用request 才能访问数据库会话。但该字段无权访问请求对象,也不知道用它调用工厂。

我的想法是直接从视图更新query_factory,但这似乎不是一个合乎逻辑的方法。当数据库会话是请求对象的一部分时,我如何使用QuerySelectField

【问题讨论】:

    标签: python sqlalchemy pyramid wtforms


    【解决方案1】:

    query_factory 仅指定要使用的 默认 查询,但 QuerySelectField will prefer the query property if it is set. 这对 Pyramid 很有用,它不鼓励直接与 threadlocal 交互。

    更改工厂以接受数据库会话。将query 设置为使用请求的数据库会话调用工厂的结果。

    def mymodel_choices(session):
        return session.query(MyModel)
    
    f = MyForm(request.POST)
    f.mymod.query = mymodel_choices(request.db_session)
    

    由于这有点不方便,您可以创建一个Form 的子类,它接受request,提取适当的表单数据,并使用请求调用每个QuerySelectField's 查询工厂。

    class PyramidForm(Form):
        def __init__(self, request, **kwargs):
            if 'formdata' not in kwargs and request.method == 'POST':
                kwargs['formdata'] = request.POST
    
            super().__init__(**kwargs)
    
            for field in self:
                if isinstance(field, QuerySelectField) and field.query_factory is not None and field.query is None:
                    field.query = field.query_factory(request.db_session)
    
    class MyForm(PyramidForm):
        ...
    
    f = MyForm(request)
    

    【讨论】:

      【解决方案2】:

      你可以尝试这样的事情(虽然它不是最干净的解决方案)

      from myapp.models import MyModel
      from pyramid import threadlocal
      
      def mymodel_choices(request=None):
          request = request or threadlocal.get_current_request()
          choices = request.DBSession.query(MyModel)
          return choices
      

      更多详情请见:http://docs.pylonsproject.org/projects/pyramid/en/latest/api/threadlocal.html

      【讨论】:

      • 我已经检查了该优先级,但文档说这是可以避免的,用户应该将其用于测试。还是谢谢
      • @JérômePigeot 我相信 wtforms 并不是为此而设计的。
      • @AnttiHaapala 如果是这样的话,对我来说这听起来像是设计失败。我正在使用 wtforms,但几乎所有表单库都需要相同的需求。我将继续以旧方式使用炼金术的脚手架:) 谢谢
      猜你喜欢
      • 1970-01-01
      • 2016-08-19
      • 1970-01-01
      • 1970-01-01
      • 2013-08-21
      • 1970-01-01
      • 2012-12-29
      • 2016-11-16
      • 1970-01-01
      相关资源
      最近更新 更多