首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Alembic:“关系”"public.alembic_version“在使用`version_table_schema`时不存在

Alembic:“关系”"public.alembic_version“在使用`version_table_schema`时不存在
EN

Stack Overflow用户
提问于 2016-04-09 02:07:18
回答 2查看 4.4K关注 0票数 1

我正在为Alembic编写一些自定义代码,以便在开发环境中始终更新项目的数据库。该项目涉及一个数据库,其内容如下:

  • 共享数据的public模式
  • 每个客户端“数据库”一个单一模式
  • 一个作为所有客户端模式(orgs)的prototype的模式。

目前,我并不担心多个客户端模式,只需要保持publicprototype模式的更新。我的env.py脚本对于public模式非常有用,但是prototype不行,因为alembic在使用prototype时试图使用public中的version表。

因此,我想我可以使用version_table_schema选项来维护public模式中的一个版本表和prototype模式中的一个版本表。然而,当我开始使用它时,当我尝试进行升级时,我会得到一个‘关系“"public.alembic_version”不存在’错误。

我看到的唯一区别是,当我将version_table_schema设置为适当的模式时,生成的修订脚本实际上包含了一行到op.drop_table('alembic_version')的代码。该行仅在使用version_table_schema时才存在。

我希望我只是错过了一些小事。

以下是供参考的所有相关源文件。唯一的外部依赖应该是appcontextgetDeclarativeBaseappcontext只用于配置,并且肯定正在工作(数据库连接正常工作)。getDeclarativeBase是一种动态获取模式声明基(和相关元数据)的方法。根据调试输出,这似乎也是正确工作的。元数据对象本身在构造时与正确的架构相关联。

运行迁移的包装器函数。autoMigratePublic()autoMigrateOrgProto()是本例中存在问题的方法。

代码语言:javascript
运行
复制
""" A wrapper around Alembic that will assist with database migrations.

    Our database system is soemwhat complex to upgrade. There is a public
    schema which we use for shared things (such as authentication and job
    management). Then there is the org prototype.

    There are also individual schemas for each client org. These are trickier.

    http://stackoverflow.com/a/35211383/703040

    Also useful:

    https://github.com/zzzeek/alembic/blob/0e3319bb36f1612e41a8d7da5a48ce1ca33a0b2b/alembic/config.py#L476
"""

import logging
import os
import time

import alembic.config
import alembic.util

CONFIG_ORG_PROTO = os.path.join("migrations", "alembic_orgproto.ini")
CONFIG_PUBLIC = os.path.join("migrations", "alembic_public.ini")

log = logging.getLogger("sys.migrations")

def autoMigratePublic():
    try:
        freezePublic()
    except alembic.util.CommandError:
        log.warn("[public] Problem creating migration revision. Skipping as this sometimes just means that we are working with a new DB.")
    upgradePublic()
    return

def autoMigrateOrgProto():
    try:
        freezeOrgProto()
    except alembic.util.CommandError:
        log.warn("[orgproto] Problem creating migration revision. Skipping as this sometimes just means that we are working with a new DB.")
    upgradeOrgProto()
    return

def freezePublic():
    log.info("[public] Checking the database for revisions...")
    alembicArgs = [
        "--config", CONFIG_PUBLIC,
        "--raiseerr",
        "revision",
        "--autogenerate",
        "--message", "autogenerate {0}".format(makeRevisionName()),
    ]
    runAlembic(alembicArgs)
    return

def freezeOrgProto():
    log.info("[orgproto] Checking the database for revisions...")
    alembicArgs = [
        "--config", CONFIG_ORG_PROTO,
        "--raiseerr",
        "revision",
        "--autogenerate",
        "--message", "autogenerate {0}".format(makeRevisionName()),
    ]
    runAlembic(alembicArgs)
    return

def makeRevisionName():
    return time.strftime('%Y-%m-%d %H:%M:%S')

def upgradePublic():
    log.info("[public] Performing database upgrade...")
    alembicArgs = [
        "--config", CONFIG_PUBLIC,
        "--raiseerr",
        "upgrade",
        "head",
    ]
    runAlembic(alembicArgs)
    return

def upgradeOrgProto():
    log.info("[orgproto] Performing database upgrade...")
    alembicArgs = [
        "--config", CONFIG_ORG_PROTO,
        "--raiseerr",
        "upgrade",
        "head",
    ]
    runAlembic(alembicArgs)
    return

def upgradeOrg(schemaName):
    log.info("[%s] Performing database upgrade...", schemaName)
    alembicArgs = [
        "--config", CONFIG_ORG_PROTO,
        "--raiseerr",
        "upgrade",
        "head",
        "-x", "schema={0}".format(schemaName),
    ]
    runAlembic(alembicArgs)
    return

def runAlembic(args):
    return alembic.config.main(args)

用于执行迁移的类。这个类在env.py文件中引用。

代码语言:javascript
运行
复制
import copy
import logging
import os
import re
import traceback

from logging.config import fileConfig

from sqlalchemy import create_engine

import core.context.appcontext
from core.database.declarative import getDeclarativeBase

logging.getLogger("alembic").setLevel(logging.DEBUG)

#==============================================================================
class Migrator(object):

    def __init__(self):
        from alembic import context
        self.context = context
        self.config = context.config
        self.log = logging.getLogger("sys.migrations")
        self.sys = core.context.appcontext.instance()
        self.schema = self.config.get_main_option("schema")
        if self.context.get_x_argument("schema"):
            self.schema = self.context.get_x_argument("schema")
        return

    def start(self):
        import core.database.tables  # Make sure the metadata is defined
        if self.context.is_offline_mode():
            self.log.error("[%s] Can't run migrations offline", self.schema)
            return
        self.doMigration()
        return

    def doMigration(self):
        targetMetadata = getDeclarativeBase(self.schema).metadata
        engine = create_engine(self.sys.getConnectionUrl(), echo=False)
        self.log.info("[%s] Engine:   %s", self.schema, engine)
        self.log.debug("[%s] Metadata: %s", self.schema, targetMetadata)
        for t in targetMetadata.sorted_tables:
            self.log.debug("    - %s", t)
        conn = engine.connect()
        try:
            self.context.configure(
                conn,
                version_table_schema=self.schema,
                target_metadata=targetMetadata,
                process_revision_directives=self.process_revision_directives,
            )
            with self.context.begin_transaction():
                self.context.run_migrations()
        finally:
            conn.close()
        return

    def process_revision_directives(self, context, revision, directives):
        """ Used to prevent creating empty migrations

            See: http://alembic.readthedocs.org/en/latest/cookbook.html#don-t-generate-empty-migrations-with-autogenerate
        """
        if self.config.cmd_opts.autogenerate:
            script = directives[0]
            if script.upgrade_ops.is_empty():
                self.log.debug("[%s] Auto-generated migration is empty. No migration file will be created.", self.schema)
                directives[:] = []
            else:
                self.log.info("[%s] Creating new auto-generated migration revision.", self.schema)
        return

env.py**.**示例公共和原型升级都有相同的内容

代码语言:javascript
运行
复制
from migrations.migrator import Migrator
Migrator().start() 

示例配置ini公共和原型迁移使用几乎完全相同的文件

代码语言:javascript
运行
复制
# A generic, single database configuration.

[alembic]
# path to migration scripts
script_location = migrations/orgproto

# template used to generate migration files
# file_template = %%(rev)s_%%(slug)s

# max length of characters to apply to the
# "slug" field
#truncate_slug_length = 40

# set to 'true' to run the environment during
# the 'revision' command, regardless of autogenerate
# revision_environment = false

# set to 'true' to allow .pyc and .pyo files without
# a source .py file to be detected as revisions in the
# versions/ directory
# sourceless = false

# version location specification; this defaults
# to alembic/versions.  When using multiple version
# directories, initial revisions must be specified with --version-path
# version_locations = %(here)s/bar %(here)s/bat alembic/versions

# the output encoding used when revision files
# are written from script.py.mako
# output_encoding = utf-8

sqlalchemy.url = <Not Loaded>

schema = orgproto

Mako --我使用的是默认设置。

代码语言:javascript
运行
复制
"""${message}

Revision ID: ${up_revision}
Revises: ${down_revision | comma,n}
Create Date: ${create_date}

"""

# revision identifiers, used by Alembic.
revision = ${repr(up_revision)}
down_revision = ${repr(down_revision)}
branch_labels = ${repr(branch_labels)}
depends_on = ${repr(depends_on)}

from alembic import op
import sqlalchemy as sa
${imports if imports else ""}

def upgrade():
    ${upgrades if upgrades else "pass"}


def downgrade():
    ${downgrades if downgrades else "pass"}
EN

Stack Overflow用户

发布于 2021-02-18 16:44:38

在我们的例子中,帮助将alembic_version添加到migrations/alembic.ini[alembic:exclude]部分

代码语言:javascript
运行
复制
[alembic:exclude]
- tables = spatial_ref_sys,topology,layer
+ tables = spatial_ref_sys,topology,layer,alembic_version

下一个在migrations/env.py

代码语言:javascript
运行
复制
context.configure(
    version_table_schema='public',
    # other params
)
票数 1
EN
查看全部 2 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36511941

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档