2016-08-19 2 views
2

Я использую wtforms_sqlalchemy в своих приложениях для пирамиды и задаю несколько QuerySelectField s. Для запроса запроса фабрика запросов использует импортированный объект DBSession.Использовать WTForms QuerySelectField с сеансом db Pyramid 1.7.

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) 

Пирамида 1,7 представила новый SQLAlchemy помост, который крепит объект дб сеанса к каждому запросу. Использование нового леса mymodel_choices должно использовать request из моего представления для доступа к сессии db. Поле не имеет доступа к объекту запроса, хотя и не знает, чтобы вызвать фабрику с ним.

Моя идея состояла в том, чтобы обновить query_factory непосредственно с точки зрения, но это не похоже на логический способ сделать это. Как я могу использовать QuerySelectField, когда сеанс db является частью объекта запроса?

ответ

1

query_factory только задает запрос по умолчанию использовать, но QuerySelectField will prefer the query property if it is set. Это полезен для Pyramid, что препятствует непосредственному взаимодействию с threadlocal.

Замените завод, чтобы принять сеанс db. Установите query на результат вызова вашей фабрики с помощью сеанса db запроса.

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) 
+1

Используя метод python2, метод super() не записывается как это, используйте ** super (Form, self) .__ init __ (** kwargs) ** –

+0

@ JérômePigeot, естественно, так было, что только давидис предположил, что вы не используете устаревшую версию Python;) –

1

Вы можете попробовать что-то вроде этого (хотя это не самый чистый раствор)

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

+0

Я уже проверял этот приоритет, но в документации говорится, что это возможность избежать, и пользователи должны просто использовать его для тестирования. Спасибо в любом случае –

+0

@ JérômePigeot Я верю, что wtforms на самом деле не предназначен для этого. –

+0

@AnttiHaapala, если это так, это звучит как неудача дизайна для меня. Я использую wtforms, но библиотеки почти всех форм потребуют одинаковых потребностей. Я просто продолжу использовать эшафот алхимии по-старому :) Спасибо –

Смежные вопросы