geekdoc-python-zh/docs/pythoncentral/migrate-sqlalchemy-database...

177 lines
7.0 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 用 Alembic 迁移 SQLAlchemy 数据库
> 原文:<https://www.pythoncentral.io/migrate-sqlalchemy-databases-alembic/>
## 蒸馏器
Alembic 是 SQLAlchemy 的一个轻量级数据库迁移工具。它是由 SQLAlchemy 的作者创建的,并且已经成为在 SQLAlchemy 支持的数据库上执行迁移的事实上的标准工具。
## SQLAlchemy 中的数据库迁移
数据库迁移通常会更改数据库的模式,例如添加列或约束、添加表或更新表。它通常使用封装在事务中的原始 SQL 来执行,以便在迁移过程中出现问题时可以回滚。在本文中,我们将使用一个示例数据库来演示如何为 SQLAlchemy 数据库编写 Alembic 迁移脚本。
为了迁移一个 SQLAlchemy 数据库,我们为计划的迁移添加一个 Alembic 迁移脚本,执行迁移,更新模型定义,然后开始在迁移的模式下使用数据库。这些步骤听起来很多,但是它们做起来非常简单,这将在下一节中进行说明。
## 示例数据库模式
让我们创建一个 SQLAlchemy 数据库,其中包含一个*部门*和一个*雇员*表。
```py
import os
from sqlalchemy 导入列DateTimeStringIntegerForeignKeyfunc
from sqlalchemy.orm 导入关系back ref
from sqlalchemy . ext . declarative import declarative _ base
Base = declarative_base()
Department(Base):
_ _ tablename _ _ = ' Department '
id = Column(Integerprimary _ key = True)
name = Column(String)
Employee(Base):
_ _ tablename _ _ = ' Employee '
id = Column(Integerprimary _ key = True)
name = Column(String)
hired _ on = Column(DateTimedefault=func.now())
db _ name = ' alem BIC _ sample . SQLite '
如果 OS . path . exists(db _ name):
OS . remove(db _ name)
sqlalchemy 导入创建引擎
引擎=创建引擎(' sqlite:///' + db_name)
sqlalchemy.orm 导入 session maker
session = session maker()
session . configure(bind = engine)
base . metadata . create _ all(engine)
```
在创建了数据库 *alembic_sample.sqlite* 之后,我们意识到我们忘记了在`Employee`和`Department`之间添加一个*多对多*关系。
## 移民
我们选择使用 alembic 迁移数据库,而不是直接更改模式,然后从头开始重新创建数据库。为此,我们安装 alembic初始化 alembic 环境,编写迁移脚本来添加链接表,执行迁移,然后使用更新的模型定义再次访问数据库。
```py
$ alembic init alembic
Creating directory /home/vagrant/python2-workspace/pythoncentral/sqlalchemy_series/alembic/alembic ... done
Creating directory /home/vagrant/python2-workspace/pythoncentral/sqlalchemy_series/alembic/alembic/versions ... done
Generating /home/vagrant/python2-workspace/pythoncentral/sqlalchemy_series/alembic/alembic/env.pyc ... done
Generating /home/vagrant/python2-workspace/pythoncentral/sqlalchemy_series/alembic/alembic.ini ... done
Generating /home/vagrant/python2-workspace/pythoncentral/sqlalchemy_series/alembic/alembic/script.py.mako ... done
Generating /home/vagrant/python2-workspace/pythoncentral/sqlalchemy_series/alembic/alembic/env.py ... done
Generating /home/vagrant/python2-workspace/pythoncentral/sqlalchemy_series/alembic/alembic/README ... done
Please edit configuration/connection/logging settings in '/home/vagrant/python2-workspace/pythoncentral/sqlalchemy_series/alembic/alembic.ini' before proceeding.
$ vim alembic.ini #将以“sqlalchemy.url”开头的行更改为“sqlalchemy . URL = SQLite:///alem BIC _ sample . SQLite”
$ alem BIC current
INFO[alem BIC . migration]Context impl SQLiteImpl
INFO [alembic.migration]将采用非事务性 DDL
SQLite 的当前版本:///alembic_sample.sqlite:
$ alem BIC revision-m " add department _ employee _ link "
生成/home/vagger/python 2-workspace/python central/sqlalchemy _ series/alem BIC/alem BIC/versions/1da 977 FD 3e 6 e _ add _ department _ employee _ link . py...完成的
$ alem BIC upgrade head
INFO[alem BIC . migration]Context impl SQL item pl
INFO [alembic.migration]将采用非事务性 DDL
信息alembic.migration运行升级无- > 1da977fd3e6e添加部门 _ 员工 _ 链接
$ alem BIC current
INFO[alem BIC . migration]Context impl SQLiteImpl
INFO [alembic.migration]将采用非事务性 DDL
当前版本为 SQLite:///alem BIC _ sample . SQLite:None->1da 977 FD 3 E6 e(负责人)添加 department_employee_link
```
迁移脚本如下:
【python】
“”
添加部门 _ 员工 _ 链接
修订 ID: 1da977fd3e6e
修订:无
创建日期:2014-10-23 22:38:42.894194
'''
#版本标识符,由 Alembic 使用。
修订版= '1da977fd3e6e'
下一版=无
从 alembic 导入操作
将 sqlalchemy 导入为 sa
def upgrade():
op . create _ table(
' department _ employee _ link '
sa。列(
'部门标识',服务协议。
整数撒。ForeignKey('department.id ')primary_key=True
)
sa。列(
'雇员标识',服务协议。整数,
sa。ForeignKey('employee.id ')primary_key=True
)
)
定义降级():
op.drop_table(
'部门 _ 员工 _ 链接'
)
现在数据库 *alembic_sample.sqlite* 已经升级,我们可以使用一段更新的模型代码来访问升级后的数据库。
```py
import os
sqlalchemy 导入列日期时间字符串整数外键func
sqlalchemy.orm 导入关系
sqlalchemy.ext.declarative 导入 declarative_base
Base = declarative_base()
class Department(Base):
_ _ tablename _ _ = ' Department '
id = Column(Integerprimary _ key = True)
name = Column(String)
employees = relationship(
' Employee '
secondary = ' Department _ Employee _ link '
)
class Employee(Base):
_ _ tablename _ _ = ' Employee '
id = Column(Integerprimary _ key = True)
name = Column(String)
hired _ on = Column(DateTimedefault = func . now())
departments = relationship(
Department
secondary = ' Department _ Employee _ link '
)
class DepartmentEmployeeLink(Base):
_ _ tablename _ _ = ' department _ employee _ link '
department _ id = Column(IntegerForeignKey('department.id ')primary_key=True)
employee _ id = Column(IntegerForeignKey('employee.id ')primary _ key = True)
db_name = 'alembic_sample.sqlite '
sqlalchemy 导入创建引擎
引擎=创建引擎(' sqlite:///' + db_name)
sqlalchemy.orm 导入 session maker
session = session maker()
session . configure(bind = engine)
base . metadata . bind = engine
s = session()
IT = Department(name = ' IT ')
Financial = Department(name = ' Financial ')
s . add(IT)
s . add(Financial)
Cathy = Employee(name = ' Cathy ')
Marry = Employee(name = ' Marry ')
John = Employee(财务)
```
注意,我们并没有删除数据库 *alembic_sample.sqlite* ,而是执行了一个迁移来添加一个链接表。迁移后,关系`Department.employees`和`Employee.departments`按预期工作。
## 摘要
由于 *Alembic* 是专门为 SQLAlchemy 构建的轻量级数据库迁移工具,它允许您重用相同类型的数据库模型 API 来执行简单的迁移。然而,它不是一个万能的工具。对于特定于数据库的迁移,比如在 PostgreSQL 中添加触发器函数,仍然需要原始的 DDL 语句。