Django.makemigrations和Alembic.revision的区别

ORM 将关系数据库映射到面向对象编程的世界。但是仅仅在 Python 文件中定义一个模型类并不能使数据库表神奇地出现。

创建数据库表来存储你的模型是数据库迁移的工作。此外,每当对模型进行更改(例如添加字段)时,也必须更改数据库。然而你无需在 SQL 中手动定义数据库表,数据库迁移通常与模型齐头并进。

这篇文章主要讲的是Django和Alemic对模型更改检测方式的不同,从配置开始讲讲。

1. 配置

1.1 Django配置

从 1.7 版开始,Django 内置了对数据库迁移的支持。内置就有内置的便利性,我们只需要在INSTALLED_APPS加入我们新创建的APP。

1.2 Alembic配置

这里Alembic与SQLAlchemy搭配使用。我们需安装alembic以及初始化文件夹

1
2
$ pip install alembic
$ alembic init migrations

配置alembic.ini

这里不用配置sqlalchemy.url了!!,

# sqlalchemy.url = postgresql://moweriot:moweriot@192.168.52.224/app

因为要根据部署环境动态的变动该属性,可以直接在env.py

config.set_main_option("sqlalchemy.url", DB_URI)进行DB_URI覆盖

配置env.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from db import DB_URI
from models import Base

# this is the Alembic Config object, which provides
# access to the values within the .ini file in use.
config = context.config

# this will overwrite the ini-file sqlalchemy.url path
# with the path given in the config of the main code
config.set_main_option("sqlalchemy.url", DB_URI)

# Interpret the config file for Python logging.
# This line sets up loggers basically.
fileConfig(config.config_file_name)

# add your model's MetaData object here
# for 'autogenerate' support
# from myapp import mymodel
# target_metadata = mymodel.Base.metadata
target_metadata = Base.metadata

2. 生成迁移

2.1 makemigarations

Django使用python manage.py makemigrations创建迁移。

工作流程是:

our models will be scanned and compared to the versions currently contained in your migration files, and then a new set of migrations will be written out. Make sure to read the output to see what makemigrations thinks you have changed - it’s not perfect, and for complex changes it might not be detecting what you expect.

这里可以看到,makemigrations是通过扫描比较当前的模型类和当前版本的migrations文件,得出一组新的迁移。这个自动生成过程有缺点:“它并不完美,对于复杂的更改,它可能无法检测到期望的内容”

2.2 revision

而对于Alembic我们使用revision命令

alembic revision --autogenerate -m "create all initial tables"

工作流程是:

Alembic can view the status of the database and compare against the table metadata in the application, generating the “obvious” migrations based on a comparison. This is achieved using the --autogenerate option to the alembic revision command, which places so-called candidate migrations into our new migrations file. We review and modify these by hand as needed, then proceed normally.

和Django不同,这里Alembic是通过查看数据库的状态并与应用程序中的表元数据进行比较,根据比较生成“明显”的迁移。这是使用 alembic revision 命令的--autogenerate选项来实现的,它将所谓的候选迁移放入我们的新迁移文件中。我们会根据需要手动审查和修改这些内容,然后正常进行。

为了使用autogenerate,我们首先需要修改我们的env.py,使它能够访问包含目标的表元数据对象。这在上面的配置中已经有体现了:

1
2
from myapp.mymodel import Base
target_metadata = Base.metadata

这个自动生成也有缺点:它也是不完美的,始终需要手动查看和更正“自动生成的候选迁移

3. 提交迁移

3.1 migrate

Django使用python manage.py migrate同步数据库迁移内容。

当然还有更多功能:因为种种原因想撤掉迁移回退到某个早期的数据库模式,这里具体不展开。

3.2 upgrade

Alembic使用alembic upgrade head同步数据库迁移内容。

当然,它也可以回退撤销到某个历史版本。其实看看Alembic的命令,倒是有几分Git的风味。

在git中可以将amelbic相关文件提交,这样在部署的时候直接拉下来,alembic upgrade head至最新版本即可,无需初始化以及生成相关语句

3.3 便捷性比较

Django因为是自带的数据库迁移,那么肯定更方便一点,比如,当提交迁移时,数据库本来存在的一些字段数据和现在的迁移有冲突,那么会提醒你解决冲突。

但是Alembic需要手动来更改字段内容:

1
2
3
4
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('cut_data', sa.Column('is_complete', sa.Boolean(), nullable=True))
op.execute("UPDATE cut_data SET is_complete = true")

还是那一点,Alembic始终需要手动查看和更正“自动生成的候选迁移”,而Django更偏于自动。

但往往在手动过程中更让初学者懂得其中具体包含的操作含义。

相关资源