首页 > 解决方案 > 插入后,转换并插入到另一个表中

问题描述

我有两张桌子DocumentPicture. 关系是一个文档可以有几张图片。应该发生的情况是,一旦将文档上传到 . PostgreSQL,该文档应该被下载并转换为 jpeg,然后上传到Picturetable。

我在我的应用程序中使用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)

标签: pythonpostgresqleventsflasksqlalchemy

解决方案


正如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#im-inserting-400-000-rows-with-the-orm-and-it -s-真的很慢

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


推荐阅读