2014-01-30 2 views
6

Я новичок в Flask и SQLAlchemy (работал с Django последние 3 года). Мне нужно позвонить существующей функции PostgreSQL, которая записывает в 3 разные таблицы в базе данных. Это вне моего контроля (я просто должен заставить его работать). Функция возвращает запись (пользовательский тип Postgres) с информацией о результатах. Вот код:Завершение транзакции из функции PostgreSQL в колбе

from flask.ext.sqlalchemy import SQLAlchemy 

db = SQLAlchemy() 

... 

retval = db.engine.execute(
    'SELECT * FROM add_purchase(%s, %s, %s, %s, %s, %s, %s);', 
    clean_data.account_id, amount, tax, deposit, clean_data.pos_id, 
    g.token_id, clean_data.external_reference_id).first() 

app.logger.info(retval) # for debugging 

db.session.commit() 

Приведенный выше код работает без ошибок. Из сообщения журнала я вижу, что правильные данные возвращаются из базы данных. Однако, если я перейду к psql, я не вижу вновь вставленные данные. Казалось бы, сделка никогда не совершается.

Большая часть документации и примеров, которые я могу найти, основана на использовании ORM SQLAlchemy. Что я здесь делаю неправильно?

Stack информация:

Flask==0.10.1 
Flask-SQLAlchemy==1.0 
psycopg2==2.5.2 
Python 2.7.3 
Postgresql 9.3 

Update

Я придумал, как заставить его работать, вот пример, который на самом деле работает для меня:

from sqlalchemy import exc 

... 

connection = db.engine.connect() 
trans = connection.begin() 
try: 
    retval = connection.execute(
     'SELECT * FROM add_purchase(%s, %s, %s, %s, %s, %s, %s);', 
     clean_data.account_id, amount, tax, deposit, 
     clean_data.pos_id, g.token_id, 
     clean_data.external_reference_id).first() 
except exc.SQLAlchemyError: 
    trans.rollback() 
    raise 
else: 
    trans.commit() 

И Я просмотрел код в методе подключения SQLAlchemy. Похоже, что вызов «connect()» просто получает новое соединение из пула (по умолчанию оно установлено на размер = 5 по умолчанию - по крайней мере, я не устанавливаю его на 5). Поэтому я не уверен, что в этом есть много вреда. Однако, похоже, должно быть сделано, чтобы сделать этот код более чистым, сделав пример в исходном вопросе. Я все еще надеюсь, что кто-то скажет мне, как это сделать.

ответ

1

Если вы используете необработанный SQL с SQLAlchemy, то я думаю, что вам нужно самостоятельно выдавать инструкции BEGIN и COMMIT. Попробуйте добавить что-то вроде этого:

... 
begin_retval = db.engine.execute('BEGIN;') 
retval = db.engine.execute('SELECT * FROM add_purchase(%s, %s, %s, %s, %s, %s, %s);', 
clean_data.account_id, amount, tax, deposit, clean_data.pos_id, 
g.token_id, clean_data.external_reference_id).first() 
commit_retval = db.engine.execute('COMMIT;') 
... 
+0

Большое спасибо за ваш ответ. Я записал этот точный код и не передал транзакцию. Это также не вызывает ошибки. –

+0

Хм. Как работает add_purchase? У вас есть код для этого? Это может быть полезно ... – Moritz

+0

Да; посмотрите пожалуйста оригинальный вопрос. «Вышеприведенный код работает без ошибок. Из сообщения журнала я вижу, что правильные данные возвращаются из базы данных». –

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