2017-02-17 2 views
0

Après des heures de débogage, et parce que mon organisation n'a pas beaucoup d'expertise Python, je me tourne vers cette communauté pour obtenir de l'aide.Je ne peux pas enregistrer des lignes dans la base de données avec SQLAchemy + Pyramid

Je suis en train de suivre this tutorial dans le but de valider certaines données dans la base de données. Bien qu'aucune erreur ne soit signalée, je n'enregistre aucune ligne. Qu'est-ce que je fais mal?

Lorsque vous essayez de commettre en utilisant le db2Session, je reçois:

transaction doit être commise à l'aide du gestionnaire de transactions.

Mais je ne vois nulle part dans le tutoriel le gestionnaire de transactions utilisé. Je pensais que ce gestionnaire est lié en utilisant zope.sqlalchemy? Pourtant, rien ne se passe autrement. Aider à nouveau serait vraiment apprécié!

je la configuration suivante dans ma fonction principale dans une application Pyramide:

from sqlalchemy import engine_from_config 
from .models import db1Session, db2Session 

def main(global_config, **settings): 
""" This function returns a Pyramid WSGI application. 
""" 
    db1_engine = engine_from_config(settings, 'db1.') 
    db2_engine = engine_from_config(settings, 'db2.') 

    db1Session.configure(bind=db1_engine) 
    db2Session.configure(bind=db2_engine) 

Dans fichiers .models/__ init__py, j'ai:

from sqlalchemy.ext.declarative import declarative_base 
from sqlalchemy.orm import (scoped_session, sessionmaker) 
from zope.sqlalchemy import ZopeTransactionExtension 

db1Session = scoped_session(sessionmaker(
    extension=ZopeTransactionExtension())) 
db2Session =  
    scoped_session(sessionmaker(extension=ZopeTransactionExtension())) 

Base = declarative_base() 

Dans ./model/db2.py I ont:

class PlateWellResult(Base): 
    __tablename__ = 'SomeTable' 
    __table_args__ = {"schema": 'some_schema'} 

    id = Column("ID", Integer, primary_key=True) 
    plate_id = Column("PlateID", Integer) 
    hit_group_id = Column("HitID", Integer, ForeignKey(
     'some_schema.HitGroupID.ID')) 
    well_loc = Column("WellLocation", String) 

Les bits pertinents de ma fonction d'économie ressemblent à ceci. ./lib/db2_api.py:

def save_selected_rows(input_data, selected_rows, hit_group_id): 
    """ Wrapper method for saving selected rows """ 
    # Assume I have all the right data below. 
    new_hit_row = PlateWellResult(
     plate_id=master_plate_id, 
     hit_group_id=hit_group_id, 
     well_loc=selected_df_row.masterWellLocation) 

    db1Session.add(new_hit_row) 
    # When I try the row below: 
    # db2Session.commit() 
    # I get: Transaction must be committed using the transaction manager 
    # If I cancel the line above, nothing gets committed. 
    return 'Save successful.' 

Cette fonction est appelée de mon spectateur:

@view_config(route_name='some_routename', renderer='json', 
      permission='create_hit_group') 
def save_to_hitgroup(self): 
    """ Backend to AJAX call to save selected rows to a hit_group """ 
    try: 
     # Assume that all values were checked and all the right 
     # parameters are passed 
     status = save_selected_rows(some_result, 
            selected_rows_list, 
            hitgroup_id) 
     json_resp = json.dumps({'errors': [], 
           'status': status}) 
     return json_resp 
    except Exception as e: 
     json_resp = json.dumps({'errors': ['Error during saving. {' 
              '0}'.format(e)], 
           'status': []}) 
     return json_resp 
+0

Si vous recherchez la page que vous avez liée pour "transaction", il y a une ligne qui utilise le gestionnaire de transactions: 'avec transaction.manager:'. Personnellement, j'évite de tels globaux alambiqués ou pseudo-globaux. Je suis beaucoup plus heureux de créer ma propre session à chaque requête. – jpmc26

+0

Avez-vous utilisé le paquet de gestion des transactions par requête ['pyramid_tm'] (http://docs.pylonsproject.org/projects/pyramid_tm/en/latest/)? Si non, alors vous ne commettez rien. Vous pouvez également utiliser le gestionnaire de transactions explicitement comme indiqué dans la publication précédente. –

+0

Oh, et si vous l'ajoutez, n'oubliez pas de manuellement 'transaction.doom()' ou 'transaction.abort()' dans votre gestionnaire d'exceptions lorsque vous les attrapez tous. –

Répondre

1

Les commentaires ci-dessus sont bons. Je voulais juste résumer ici.

Le gestionnaire de transactions est démarré/validé/annulé par pyramid_tm. Si vous n'utilisez pas cela, c'est probablement le problème.

Vous écrasez également les exceptions de base de données possibles qui doivent être transmises au gestionnaire de transactions. Vous pouvez le faire via transaction.abort() dans le gestionnaire d'exceptions.