在sqlalchemy中修改表的定义后,是否可以恢复表的旧数据?

时间:2019-03-23 22:33:38

标签: python flask-sqlalchemy

说,有一个movie.py,它包含电影和基本内容的表定义,例如

# base.py
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
engine = create_engine('postgresql://usr:pass@localhost:5432/sqlalchemy')
Session = sessionmaker(bind=engine)
Base = declarative_base()
# move.py
from sqlalchemy import Column, String, Integer, Date
from base import Base
class Movie(Base):
    __tablename__ = 'movies'

    id = Column(Integer, primary_key=True)
    title = Column(String)
    release_date = Column(Date)

    def __init__(self, title, release_date):
        self.title = title
        self.release_date = release_date

并插入一些查询,例如

# coding=utf-8
from datetime import date
from base import Session, engine, Base
from movie import Movie

# 2 - generate database schema
Base.metadata.create_all(engine)

# 3 - create a new session
session = Session()

# 4 - create movies
bourne_identity = Movie("The Bourne Identity", date(2002, 10, 11))
furious_7 = Movie("Furious 7", date(2015, 4, 2))
pain_and_gain = Movie("Pain & Gain", date(2013, 8, 23))

# 5 - persists data
session.add(bourne_identity)
session.add(furious_7)
session.add(pain_and_gain)


# 10 - commit and close session
session.commit()
session.close()

如果我对电影表有了新的定义(将更多列添加到move.py中),是否可以恢复插入的旧数据?

1 个答案:

答案 0 :(得分:0)

您的意思是问“如何更新现有数据库的数据库架构?”。这就是所谓的“模式迁移”。有多种攻击方法。最基本的方法是让SqlAlchemy在另一个方向上工作...让它从现有数据库生成其架构元数据,而不是创建元数据,然后让SqlAlchemy从该数据库构建数据库。这称为Reflection。您将执行此操作,然后发出单独的命令来更新数据库架构。为此,您必须考虑到进行这些更改时表中现有行将要发生的情况。您仍将使用域对象定义(Movie对象),但不会使用create_all()。 create_all()会忽略任何已存在的表。

实际上,这很快变得很复杂,因此您通常希望使用正式的架构迁移策略,并且可能需要使用支持包。 SqlAlchemy自己的文档建议使用两个程序包。看到此页面:

https://docs.sqlalchemy.org/en/latest/core/metadata.html

向下滚动至“通过迁移更改架构”部分。

在没有迁移软件包的情况下,有人可能会为您提供更多有关如何手动执行此操作的信息。我一直将这样的程序包用于任何我不愿意丢失数据并在架构更改时从头开始的任务。

我见过的另一个选择是导出所有数据,让SqlAlchemy构建一个新的空数据库,然后将现有数据导入回该新数据库。您将为传入数据中不存在的新字段设置适当的默认值。无论您选择如何解决此问题,都将通过为缺少的列设置默认值来做到这一点。