2012-06-15 5 views
2

Je l'ai en cours d'exécution sur un site Web en direct. Lorsqu'un utilisateur se connecte, j'interroge son profil pour voir combien de "crédits" il a à sa disposition. Les crédits sont achetés via paypal. Si une personne achète des crédits et que le paiement lui parvient, la requête affiche toujours 0 crédit, bien que si j'exécute la même requête dans phpmyadmin, elle apporte le bon résultat. Si je redémarre le serveur web Apache et recharge la page, le nombre de crédits est affiché. Voici mon code mappeur qui montre le nombre de crédits par chaque utilisateur:sqlalchemy mise en cache de certaines requêtes

mapper(User, users_table, order_by = 'user.date_added DESC, user.id DESC', properties = { 
    'userCreditsCount': column_property( 
     select( 
      [func.ifnull(func.sum(orders_table.c.quantity), 0)], 
      orders_table.c.user_id == users_table.c.id 
     ).where(and_( 
      orders_table.c.date_added > get_order_expire_limit(), # order must not be older than a month 
      orders_table.c.status == STATUS_COMPLETED 
     )).\ 
     label('userCreditsCount'), 
     deferred = True 
    ) 
    # other properties.... 
}) 

J'utilise sqlalchemy avec le cadre de flacon mais pas en utilisant leur paquet flacon-sqlalchemy (juste sqlalchemy pur)

Voici comment je lance ma base de données:

engine = create_engine(config.DATABASE_URI, pool_recycle = True) 
metadata = MetaData() 
db_session = scoped_session(sessionmaker(bind = engine, autoflush = True, autocommit = False)) 

Je l'ai appris à la fois python et sqlalchemy sur ce projet afin que je puisse être absent des choses, mais celui-ci me conduit noix. Des idées?

Répondre

0

ensemble sessionmaker « de la autocommit True et voir si cela aide, selon la documentation de caches sessionmaker

le modèle de carte d'identité, et stocke les objets renvoient à leurs clé primaire. Cependant, il ne fait aucune sorte de mise en cache des requêtes.

donc dans votre code deviendrait:

sessionmaker(bind = engine, autoflush = True, autocommit = True) 
+0

Je ne pense pas que l'autocommit défini sur True soit un moyen intelligent. Ils ne le recommandent même pas sur leurs documents. –

2

S'il vous plaît essayez d'appeler refresh or expire sur votre objet avant d'accéder au champ userCreditsCount:

user1 = session.query(User).get(1) 
# ... 
session.refresh(user1, ('userCreditsCount',)) 

Cela fera à nouveau la requête exécuter (lorsque l'actualisation est appelée). Toutefois, en fonction du mode d'isolation utilisé par votre transaction, le problème peut ne pas être résolu, auquel cas vous devrez peut-être valider/annuler la transaction (session) pour que la requête vous donne un nouveau résultat.

1

Lifespan of a Contextual Session

Je vous assure que la fermeture de la session lorsque vous avez terminé avec elle.

session = db_session() 
try: 
    return session.query(User).get(5) 
finally: 
    session.close() 
3

lorsque vous travaillez avec une session, dès qu'il commence à travailler avec une connexion, il en est sur cette connexion jusqu'à commit(), rollback() ou close() est appelée. Avec DBAPI, la connexion à la base de données reste également dans une transaction jusqu'à ce que la transaction soit validée ou annulée. Dans ce cas, lorsque vous avez chargé des données dans votre session, SQLAlchemy n'actualise pas les données tant que la transaction n'est pas terminée (ou si vous expirez explicitement une partie des données avec expire()). C'est le comportement naturel à avoir, car en raison de transaction isolation, il est très probable que la transaction en cours ne peut pas voir les changements qui ont eu lieu depuis que cette transaction a commencé dans tous les cas. Donc, si vous utilisez expire() ou refresh() pour obtenir les dernières données dans votre session, vous devez vraiment terminer votre transaction et en commencer une nouvelle pour voir ce qui a changé ailleurs depuis que cette transaction a commencé.vous devez organiser votre application de manière à ce qu'une Session() particulière soit prête à partir lorsqu'une nouvelle requête arrive, mais lorsque cette requête est terminée, la Session() doit être fermée, et une nouvelle (ou au moins une nouvelle transaction) démarré sur la prochaine demande.

Questions connexes