可以在alembic.ini之外存储alembic连接字符串吗?
我在用Alembic配合SQLAlchemy。通常,我的做法是把连接数据库的字符串(也就是连接信息)和版本代码分开存储。我会创建一个叫secret.py
的文件,把所有的机密信息放在里面。然后我把这个文件名加到.gitignore
里,这样它就不会被上传到GitHub上。
这个方法一直都挺好用,但现在我开始用Alembic来处理数据库迁移了。问题是,我发现我不能把连接字符串隐藏起来。在alembic.ini
文件里,我需要把连接字符串放在一个配置参数里:
# the 'revision' command, regardless of autogenerate
# revision_environment = false
sqlalchemy.url = driver://user:pass@localhost/dbname
# Logging configuration
[loggers]
keys = root,sqlalchemy,alembi
我担心会不小心把包含数据库用户名和密码的信息的文件提交上去。我希望能把这个连接字符串放在一个地方,这样就能避免不小心把它提交到版本控制系统里的风险。
我还有哪些选择呢?
15 个回答
env.py:
from alembic.config import Config
alembic_cfg = Config()
alembic_cfg.set_main_option("sqlalchemy.url", getenv('PG_URI'))
看起来可以通过在 env.py
文件中重新实现引擎创建来解决问题,这个文件显然是用来进行这种自定义的地方,而不是在 ini 文件中使用 sqlalchemy 的连接字符串:
engine = engine_from_config(
config.get_section(config.config_ini_section),
prefix='sqlalchemy.',
poolclass=pool.NullPool)
你可以替换并指定自己的引擎配置:
import store
engine = store.engine
实际上,文档中 似乎暗示 这样做是可以的:
sqlalchemy.url - 这是一个通过 SQLAlchemy 连接到数据库的 URL。这个键实际上只在特定于“通用”配置的 env.py 文件中被引用;这个文件可以由开发者自定义。多个数据库配置可能会对应多个键,或者可能引用文件的其他部分。
Alembic 的文档建议使用 create_engine
来创建数据库连接,直接用数据库的地址,而不是像在代码中修改 sqlalchemy.url。
另外,你还需要修改 run_migrations_offline
这个函数,让它使用新的数据库地址。Allan Simon 在他的博客上有一个例子,但简单来说,你需要修改 env.py
文件,步骤如下:
提供一个共享的函数来获取数据库地址(这里是从命令行获取的):
def get_url(): url = context.get_x_argument(as_dictionary=True).get('url') assert url, "Database URL must be specified on command line with -x url=<DB_URL>" return url
在离线模式下使用这个地址:
def run_migrations_offline(): ... url = get_url() context.configure( url=url, target_metadata=target_metadata, literal_binds=True) ...
在在线模式下使用
create_engine
来代替engine_from_config
:def run_migrations_online(): ... connectable = create_engine(get_url()) with connectable.connect() as connection: ...
为了避免把我的用户名和密码写进代码里,我想到的最简单的方法就是:a) 在 alembic.ini
文件里加入插值字符串,b) 在 env.py
文件里设置这些插值的值。
alembic.ini
sqlalchemy.url = postgresql://%(DB_USER)s:%(DB_PASS)s@35.197.196.146/nozzle-website
env.py
import os
from logging.config import fileConfig
from sqlalchemy import engine_from_config
from sqlalchemy import pool
from alembic import context
# this is the Alembic Config object, which provides
# access to the values within the .ini file in use.
config = context.config
# here we allow ourselves to pass interpolation vars to alembic.ini
# fron the host env
section = config.config_ini_section
config.set_section_option(section, "DB_USER", os.environ.get("DB_USER"))
config.set_section_option(section, "DB_PASS", os.environ.get("DB_PASS"))
...
我昨天也遇到了同样的问题,找到了解决办法。我的做法是在 alembic/env.py
文件中这样写:
# 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
import config as ems_config
config.set_main_option('sqlalchemy.url', ems_config.config.get('sql', 'database'))
ems_config
是一个外部模块,用来存放我的配置数据。
config.set_main_option(...)
这个命令主要是用来覆盖 alembic.ini
文件中 [alembic]
部分的 sqlalchemy.url
这个选项。在我的配置中,我干脆把它留空。