gpt4 book ai didi

python - Alembic 自动生成不检测具有大小写混合名称的现有表

转载 作者:行者123 更新时间:2023-12-04 14:14:06 25 4
gpt4 key购买 nike

当我想使用 alembic 进行自动生成迁移时出现错误。

项目树:

-   alembic.ini
- axis.py
- tree.txt
-
alembic
- env.py
- README
- script.py.mako

versions
# A generic, single database configuration.

[alembic]
# path to migration scripts
script_location = alembic

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

# timezone to use when rendering the date
# within the migration file as well as the filename.
# string value is passed to dateutil.tz.gettz()
# leave blank for localtime
# timezone =

# 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 = mysql+pymysql://root:**********$@localhost/amatdb_test


[post_write_hooks]
# post_write_hooks defines scripts or Python functions that are run
# on newly generated revision scripts. See the documentation for further
# detail and examples

# format using "black" - use the console_scripts runner, against the "black" entrypoint
# hooks=black
# black.type=console_scripts
# black.entrypoint=black
# black.options=-l 79

# Logging configuration
[loggers]
keys = root,sqlalchemy,alembic

[handlers]
keys = console

[formatters]
keys = generic

[logger_root]
level = WARN
handlers = console
qualname =

[logger_sqlalchemy]
level = WARN
handlers =
qualname = sqlalchemy.engine

[logger_alembic]
level = INFO
handlers =
qualname = alembic

[handler_console]
class = StreamHandler
args = (sys.stderr,)
level = NOTSET
formatter = generic

[formatter_generic]
format = %(levelname)-5.5s [%(name)s] %(message)s
datefmt = %H:%M:%S

轴.py

from sqlalchemy import create_engine
import pymysql
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, ForeignKey, UniqueConstraint

Base = declarative_base()
engine = create_engine('mysql+pymysql://root:*******$@localhost/amatdb_test')

#The axis on which the tests are executed
class AXIS(Base):
__tablename__ = 'Axis'
id_axis = Column(Integer, primary_key = True)
name_axis = Column(String(10), nullable=False)

env.py

from logging.config import fileConfig
from sqlalchemy import engine_from_config
from sqlalchemy import pool

from alembic import context

import sys
import os

sys.path.insert(0, os.getcwd())
print(sys.path)
from axis import Base

print(Base.metadata.sorted_tables)


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

# 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

# other values from the config, defined by the needs of env.py,
# can be acquired:
# my_important_option = config.get_main_option("my_important_option")
# ... etc.


def run_migrations_offline():
"""Run migrations in 'offline' mode.

This configures the context with just a URL
and not an Engine, though an Engine is acceptable
here as well. By skipping the Engine creation
we don't even need a DBAPI to be available.

Calls to context.execute() here emit the given string to the
script output.

"""
url = config.get_main_option("sqlalchemy.url")
context.configure(
url=url,
target_metadata=target_metadata,
literal_binds=True,
dialect_opts={"paramstyle": "named"},
)

with context.begin_transaction():
context.run_migrations()


def run_migrations_online():
"""Run migrations in 'online' mode.

In this scenario we need to create an Engine
and associate a connection with the context.

"""
connectable = engine_from_config(
config.get_section(config.config_ini_section),
prefix="sqlalchemy.",
poolclass=pool.NullPool,
)

with connectable.connect() as connection:
context.configure(
connection=connection, target_metadata=target_metadata
)

with context.begin_transaction():
context.run_migrations()


if context.is_offline_mode():
run_migrations_offline()
else:
run_migrations_online()

我的问题说明

首先,我创建了我的第一个自动生成迁移:alembic revision --autogenerate

迁移文件似乎是正确的。

"""Creation table

Revision ID: dcd02a3f6ff9
Revises:
Create Date: 2020-06-03 08:47:48.198022

"""
from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision = 'dcd02a3f6ff9'
down_revision = None
branch_labels = None
depends_on = None


def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('Axis',
sa.Column('id_axis', sa.Integer(), nullable=False),
sa.Column('name_axis', sa.String(length=10), nullable=False),
sa.PrimaryKeyConstraint('id_axis')
)
# ### end Alembic commands ###


def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_table('Axis')
# ### end Alembic commands ###

然后,我运行:alembic upgrade head

我的数据库已创建。

因此,我向表轴添加了一个名为“test”的新列。

test           = Column(String(10), default=None)

我第二次运行: alembic revision --autogenerate
我获得了这个迁移文件

"""Ajout colonne test dans axis

Revision ID: 283ca08aec66
Revises: dcd02a3f6ff9
Create Date: 2020-06-03 08:49:19.717515

"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import mysql

# revision identifiers, used by Alembic.
revision = '283ca08aec66'
down_revision = 'dcd02a3f6ff9'
branch_labels = None
depends_on = None


def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('Axis',
sa.Column('id_axis', sa.Integer(), nullable=False),
sa.Column('name_axis', sa.String(length=10), nullable=False),
sa.Column('test', sa.String(length=10), nullable=True),
sa.PrimaryKeyConstraint('id_axis')
)
op.drop_table('axis')
# ### end Alembic commands ###


def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('axis',
sa.Column('id_axis', mysql.INTEGER(), autoincrement=True, nullable=False),
sa.Column('name_axis', mysql.VARCHAR(length=10), nullable=False),
sa.PrimaryKeyConstraint('id_axis'),
mysql_collate='utf8mb4_0900_ai_ci',
mysql_default_charset='utf8mb4',
mysql_engine='InnoDB'
)
op.drop_table('Axis')
# ### end Alembic commands ###

如您所见,alembic 尝试重新创建表格轴。所以,当我运行时: alembic upgrade head
我收到一个错误,因为轴已经存在。

我错过了什么 ?

为什么 Alembic 无法检测到现有表?

感谢您的时间和考虑

最佳答案

尝试使用小写的表名,即。 axis而不是 Axis .我不确定 mysql 甚至支持大写表名,但这可能会导致问题。

可能发生的情况的一个例子,mysql 可能会默默地将名称小写,因此第一次使用 alembic 比较 Axis无所事事,去做 Axis它可以工作,但 mysql 默默地创建 axis .第二次alembic看没有Axis ,所以它试图创建 Axis再次,mysql 小写它并创建表失败,因为 axis已经存在。此外,Alembic 锯还有一个 axis ,所以它会删除该表,因为它不是 Axis而不是在 sqlalchemy 模式中。

无论哪种方式,只使用小写字母都可能更安全。

关于python - Alembic 自动生成不检测具有大小写混合名称的现有表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62167360/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com