插入后,转换并插入到另一个表中

时间:2019-07-10 13:10:39

标签: python postgresql events flask sqlalchemy

我有两个表DocumentPicture。关系是一个文件可以有多张图片。应该发生的事情是,一旦将文档上传到PostgreSQL,就应该下载该文档并将其转换为jpeg,然后再上传到Picture表中。

我在应用程序中使用sqlalchemyflask。 到目前为止,我尝试使用events在插入后触发方法。不幸的是,我在提交时收到错误sqlalchemy.exc.ResourceClosedError: This transaction is closed

代码:

from app.models.ex_model import Document, Picture
from pdf2image import convert_from_bytes
from sqlalchemy import event
import io
import ipdb

from app.core.app_setup import db
@event.listens_for(Document, 'after_insert')
def receive_after_insert(mapper, connection, target):
    document = target.document

    images = convert_from_bytes(document, fmt='jpeg')
    images_bytes = map(lambda img: convert_to_byte(img), images)
    map(lambda img_byte: upload_picture(img_byte, target.id, ), images_bytes)

    db.session.commit()


def convert_img_to_byte(img):
    img_byte = io.BytesIO()
    img.save(img_byte, format='jpeg')
    img_byte = img_byte.getvalue()
    return img_byte

def upload_picture(img_byte, document_id):
    picture = Picture(picture=img_byte, document_id=document_id)
    db.session.add(picture)

1 个答案:

答案 0 :(得分:0)

Session.add方法指出:

  

其状态将在下一个flush上保存到数据库中   操作。
add()的重复调用将被忽略。

因此,在您的add呼叫之后应进行session.flush()呼叫。

...
def upload_picture(img_byte, document_id):
    picture = Picture(picture=img_byte, document_id=document_id)
    db.session.add(picture)
    db.session.flush()

此外,我将注意插入记录的性能。关于这一点,官方文档中有一篇不错的文章:https://docs.sqlalchemy.org/en/13/faq/performance.html#i-m-inserting-400-000-rows-with-the-orm-and-it-s-really-slow

因此,当前的方法不是最快的方法,因此我会选择sqlalchemy_orm_bulk_insertsqlalchemy_core方法。