如何从SQLAlchemy会话中分离对象,以便我可以将它们插入到不同的数据库中?

时间:2015-11-26 20:19:09

标签: python sqlalchemy

我有两个数据库(srcdst),每个数据库使用相同的SQLAlchemy模型。我想查询src并将该查询的结果插入dst

当我尝试将src中的值插入dst时,我的代码会抛出InvalidRequestError异常,因为查询的对象已附加到src会话。

#!/usr/bin/env python

from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.exc import InvalidRequestError
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

Base = declarative_base()


class User(Base):
    __tablename__ = 'users'

    uid = Column(Integer, primary_key=True)
    username = Column(String, unique=True, nullable=False)
    gid = Column(Integer, nullable=False)
    password = Column(String)
    gecos = Column(String)
    home_directory = Column(String)
    shell = Column(String)

    def __init__(self, passwd_string):
        passwd_fields = passwd_string.split(':')
        self.username = passwd_fields[0]
        self.password = passwd_fields[1]
        self.uid = passwd_fields[2]
        self.gid = passwd_fields[3]
        self.gecos = passwd_fields[4]
        self.home_directory = passwd_fields[5]
        self.shell = passwd_fields[6]


def get_session(db_uri):
    engine = create_engine(db_uri)
    Base.metadata.create_all(engine)
    return sessionmaker(bind=engine)()


def add_users(session, user_list):
    session.add_all(user_list)
    session.commit()


def main():
    users = [
        User('root:x:0:0:Root User:/:/bin/bash'),
        User('genuser:x:100:100:Generic User:/home/user:/bin/bash')
    ]

    # insert users to src database
    src = get_session('sqlite:///src.sqlite')
    add_users(src, users)

    # query src database for users
    src_users = src.query(User).all()

    # insert users found in src database into dst database
    try:
        dst = get_session('sqlite:///dst.sqlite')
        add_users(dst, src_users)
    except InvalidRequestError as error:
        print "InvalidRequestError: {}".format(error)


if __name__ == "__main__":
    main()

在代码上运行会生成以下异常/错误:

InvalidRequestError: Object '<User at 0x10bc10250>' is already attached to session '1' (this is '2')

为了回应@ Deepak的回答,我在User中实现了copy()方法:

def copy(self):
    return User(
        '{}:{}:{}:{}:{}:{}:{}'.format(
            self.username,
            self.password,
            self.uid,
            self.gid,
            self.gecos,
            self.home_directory,
            self.shell
        )
    )

这意味着我现在可以做到:

try:
    dst = get_session('sqlite:///dst.sqlite')
    dst.add(user.copy()) for user in src_users
except InvalidRequestError as error:
    print "InvalidRequestError: {}".format(error)

1 个答案:

答案 0 :(得分:0)

您正尝试通过数据库1的会话进行查询,并将此会话的附加用户对象插入另一个会话。 更好的方法是在第二个表中插入值,方法与在第一个表中插入的方式相同。 所以从表1中获取值:

src_users = src.query(User).all()
duplicate_records = []
for row in src.query(User).all(): 
    duplicate_user.append(User(row.username +":"+ row.password +":"+str(row.uid)+":"+str(row.gid)+":"+row.gecos+":"+row.home_directory+":"+row.shell))

然后将此列表插入第二个表格。