Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql 使用sqlalchemy将一个对象从一个数据库持久化到另一个数据库_Mysql_Python 3.x_Sqlalchemy_Multiple Databases - Fatal编程技术网

Mysql 使用sqlalchemy将一个对象从一个数据库持久化到另一个数据库

Mysql 使用sqlalchemy将一个对象从一个数据库持久化到另一个数据库,mysql,python-3.x,sqlalchemy,multiple-databases,Mysql,Python 3.x,Sqlalchemy,Multiple Databases,我有两个数据库(都是Mysql),它们有完全相同的表,我想使用Sqlalchemy将一些数据从一个数据库复制到另一个数据库 我可以根据这个问题的答案复制简单对象: 问题是当对象具有来自另一个表的依赖项时,我也想复制这些依赖项 因此,更清楚地说,这是我的模型(两个数据库相同,但使用指向不同数据库的不同bind_键): 我想做的是: from models1 import Payment as Payment1 from models2 import Payment as Payment2 #

我有两个数据库(都是Mysql),它们有完全相同的表,我想使用Sqlalchemy将一些数据从一个数据库复制到另一个数据库

我可以根据这个问题的答案复制简单对象:

问题是当对象具有来自另一个表的依赖项时,我也想复制这些依赖项

因此,更清楚地说,这是我的模型(两个数据库相同,但使用指向不同数据库的不同bind_键):

我想做的是:

from models1 import Payment as Payment1
from models2 import Payment as Payment2

# query from one database
payment1 = db1.session.query(Payment1).first()

# create and add it to the other database
payment2 = Payment2(**payment1.__dict__.copy())
db2.session.add(payment)
db2.session.commit()
但是在本例中,外键失败,因为我还没有存储PaymentMethod

是否有不同的方法来实现这一点,或者我必须对对象的每个依赖项执行此过程,并确保事先存储子对象


非常感谢您的帮助:)

我想出了一个解决方案,可以将对象重新映射到正确的模型并存储其所有子对象。调用方法
save_obj
并传递要映射的对象。然后,它将检索一个具有相同名称的表,但从要将对象重新映射到的模型中检索,并且它将递归地对其所有子对象执行相同的操作。您必须在方法
get\u model
中定义正确的模型

要运行此操作,必须禁用自动刷新以防止在正确形成对象之前提交,还必须在调用该方法后提交。我在用炼金术

希望这能对面临类似问题的人有所帮助或启发:)

from models1 import Payment as Payment1
from models2 import Payment as Payment2

# query from one database
payment1 = db1.session.query(Payment1).first()

# create and add it to the other database
payment2 = Payment2(**payment1.__dict__.copy())
db2.session.add(payment)
db2.session.commit()
def save_obj(obj, checked=[]):
    if obj in checked:
        # if the object was already converted, retrieve the right object
        model = get_model(obj.__mapper__.mapped_table.name)
        return get_obj(obj, model)

    checked.append(obj)
    children = []

    relations = obj.__mapper__.relationships.items()

    # get all the relationships of this model (foreign keys)
    for relation in relations:
        model = get_model(relation[1].table.name)
        if model:
            # remove the cascade option for this object, so the children are not stored automatically in the session
            relation[1]._cascade = CascadeOptions('')
            child = getattr(obj, relation[0])

            if not child:
                continue

            # if the child is a set of children
            if isinstance(child, list):
                new_children = []
                for ch in copy(child):
                    # convert the child
                    new_child = save_obj(ch, checked)
                    new_children.append(new_child)

                children.append((relation[0], new_children))
            else:
                new_child = save_obj(child, checked)
                children.append((relation[0], new_child))

    # get the model of the object passed
    model = get_model(obj.__mapper__.mapped_table.name)
    new_obj = get_obj(obj, model)

    # set all the children in this object
    for child in children:
        if child[1]:
            setattr(new_obj, child[0], child[1])

    checked.append(new_obj)

    session.add(new_obj)
    return new_obj


def get_model(table_name):
    # get the right model for this object
    for table in db.Model._decl_class_registry.values():
        if hasattr(table, '__tablename__') and table.__tablename__ == table_name:
            return table
    return None


def create_new_obj(obj, model):
    params = obj.__dict__.copy()
    params.pop('_sa_instance_state')
    return model(**params)


def get_obj(child, model):
    # check if the object is already stored in the db
    child_in_db = session.query(model).get(child.id)

    if child_in_db:
        return child_in_db

    # check if the object is already in the session
    for s in session.new:
        if type(s) == model and s.id == child.id:
            return s

    return create_new_obj(child, model)