2015-06-25 2 views
1

Я создаю приложение для флэков, и я хочу использовать sqlalchemy observers, чтобы обновить статус отправки после того, как все продукты внутри этой партии станут доступны.сеанс уже смывается, когда я использую @observes

Вот мой DataModel:

from app import db 
from sqlalchemy_utils import observes 

class Shipment(db.Model): 
    __tablename__ = 'shipment' 
    id = db.Column(db.Integer, primary_key=True) 
    products = db.relationship('Product', backref='shipment', lazy='dynamic') 
    all_products_ready = db.Column(db.Boolean) 

    @observes('products') 
    def product_observer(self, products): 
     for p in self.products: 
      if p.status != 'ready': 
       self.all_products_ready = False 
       return False 
     self.all_products_ready = True 
     return True 

class Product(db.Model): 
    __tablename__ = 'product' 
    id = db.Column(db.Integer, primary_key=True) 
    shipment_id = db.Column(db.Integer, db.ForeignKey('shipment.id')) 

    status = db.Column(db.String(120), index=True) 

А вот некоторый код я бегу, чтобы проверить это:

shipment = models.Shipment(products=[models.Product(status='ready'), models.Product(status='not_ready')]) 
db.session.add(shipment) 
db.session.commit() 

print(shipment.all_products_ready) 

Когда я запускаю этот код я получаю InvalidRequestError: Session уже промывке.

Вот трассировки стека:

Traceback (most recent call last): 
    File "test.py", line 5, in <module> 
    db.session.commit() 
    File "U:\dev\observertest\flask\lib\site-packages\sqlalchemy\orm\scoping.py", 
line 150, in do 
    return getattr(self.registry(), name)(*args, **kwargs) 
    File "U:\dev\observertest\flask\lib\site-packages\sqlalchemy\orm\session.py", 
line 788, in commit 
    self.transaction.commit() 
    File "U:\dev\observertest\flask\lib\site-packages\sqlalchemy\orm\session.py", 
line 384, in commit 
    self._prepare_impl() 
    File "U:\dev\observertest\flask\lib\site-packages\sqlalchemy\orm\session.py", 
line 364, in _prepare_impl 
    self.session.flush() 
    File "U:\dev\observertest\flask\lib\site-packages\sqlalchemy\orm\session.py", 
line 1985, in flush 
    self._flush(objects) 
    File "U:\dev\observertest\flask\lib\site-packages\sqlalchemy\orm\session.py", 
line 2012, in _flush 
    self.dispatch.before_flush(self, flush_context, objects) 
    File "U:\dev\observertest\flask\lib\site-packages\sqlalchemy\event\attr.py", l 
ine 221, in __call__ 
    fn(*args, **kw) 
    File "U:\dev\observertest\flask\lib\site-packages\sqlalchemy_utils\observer.py 
", line 272, in invoke_callbacks 
    for (root_obj, func, objects) in args: 
    File "U:\dev\observertest\flask\lib\site-packages\sqlalchemy_utils\observer.py 
", line 252, in gather_callback_args 
    lambda obj: obj not in session.deleted 
    File "U:\dev\observertest\flask\lib\site-packages\sqlalchemy_utils\functions\o 
rm.py", line 741, in getdotattr 
    last = [v for v in last if condition(v)] 
    File "U:\dev\observertest\flask\lib\site-packages\sqlalchemy\orm\dynamic.py", 
line 245, in __iter__ 
    sess = self.session 
    File "U:\dev\observertest\flask\lib\site-packages\sqlalchemy\orm\dynamic.py", 
line 237, in session 
    sess.flush() 
    File "U:\dev\observertest\flask\lib\site-packages\sqlalchemy\orm\session.py", 
line 1979, in flush 
    raise sa_exc.InvalidRequestError("Session is already flushing") 
sqlalchemy.exc.InvalidRequestError: Session is already flushing 

Как я могу использовать мои модели не получаю эту ошибку?

ответ

1

Я не совсем уверен, почему, но я думаю, что загрузка отношений с использованием dynamic вызывает проблемы здесь. В этой строке:

products = db.relationship('Product', backref='shipment', lazy='dynamic') 

вам необходимо изменить параметр lazy в select вместо dynamic (или вы можете взять параметр lazy ALLtogether в select является по умолчанию).

См. the sqlalchemy reference для всех доступных опций.