将 WTForms QuerySelectField 与 Pyramid 1.7 的数据库会话一起使用
Use WTForms QuerySelectField with Pyramid 1.7's db session
我在我的金字塔应用程序中使用 wtforms_sqlalchemy 并定义了几个 QuerySelectField
。查询工厂使用导入的 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
?
您可以尝试这样的方法(尽管这不是最干净的解决方案)
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
query_factory
仅指定要使用的 default 查询,但是 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)
我在我的金字塔应用程序中使用 wtforms_sqlalchemy 并定义了几个 QuerySelectField
。查询工厂使用导入的 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
?
您可以尝试这样的方法(尽管这不是最干净的解决方案)
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
query_factory
仅指定要使用的 default 查询,但是 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)