首页 > 解决方案 > Flask SqlAlchemy/Alembic 迁移将无效字符集发送到 PyMysql

问题描述

在过去的 21 天中,有 18 天我为此花费了 3 多个小时。请有人告诉我我的误解是什么!

TL;DR:我的代码反复将 db 字符集作为字符串发送到 PyMysql,而它需要一个具有名为“encoding”的属性的对象

背景

这是在 docker 容器上运行的 Python 代码。第二个容器容纳数据库。数据库地址存储在一个.env名为的变量中ENGINE_URL

ENGINE_URL=mysql+pymysql://root:@database/starfinder_development?charset=utf8

我正在使用clickCLI 中的命令启动 Alembic 和 Flask-Alembic 命令。以下所有方法都在 CLI 命令中使用。

模型/数据库设置(作品)

from flask import Flask
flask_app = Flask(__name__)

db_engine = SQLAlchemy(flask_app)

from my_application import models

def create_database():
    db_engine.create_all()

此时我可以打开数据库容器并使用 MySql CLI 看到我的所有模型现在都已转换为具有列和关系的表。

尝试 1:Alembic

使用 Alembic 创建修订文件(作品)

from alembic.config import Config

def main(): # fires prior to any CLI command
    filepath = os.path.join(os.path.dirname(__file__),
                            "alembic.ini")
    alembic_config = Config(file_=filepath)
    alembic_config.set_main_option("sqlalchemy.url",
                                   ENGINE_URL)
    alembic_config.set_main_option("script_location",
                                   SCRIPT_LOCATION)
    migrate_cli(obj={"alembic_config": alembic_config})

def revision(ctx, message):
    alembic_config = ctx.obj["alembic_config"]
    alembic_command.revision(alembic_config, message)

此时我有一个迁移文件,它完全按照预期创建。然后我需要使用该迁移升级数据库......

使用 Alembic 运行迁移(失败)

def upgrade(ctx, migration_revision):
    alembic_config = ctx.obj["alembic_config"]
    migration_revision = migration_revision.lower()
    _dispatch_alembic_cmd(alembic_config, "upgrade",
                          revision=migration_revision)

触发它cli_command upgrade head会导致失败,我将其包含在底部,因为它与我的第二次尝试具有相同的堆栈跟踪。

尝试 2:Flask-Alembic

这次尝试发现我完全重写了我的mainrevision命令,但它并没有达到使用upgrade.

使用 Flask-Alembic 创建修订文件(失败)

def main(): # fires prior to any CLI command
    alembic_config = Alembic()
    alembic_config.init_app(flask_app)
    migrate_cli(obj={"alembic_config": alembic_config})

def revision(ctx, message):
    with flask_app.app_context():
        alembic_config = ctx.obj["alembic_config"]
        print(alembic_config.revision(message))

这会导致与我之前尝试的错误相同的错误。

两种情况下的堆栈跟踪:

(使用蒸馏器升级和烧瓶蒸馏器修订相同的失败)

File "/Users/MyUser/.pyenv/versions/3.6.2/envs/sf/lib/python3.6/site-packages/pymysql/connections.py", line 678, in __init__
self.encoding = charset_by_name(self.charset).encoding
AttributeError: 'NoneType' object has no attribute 'encoding'

作为回应,我进入了上述文件并L677在错误之前添加了一个 print on :

打印(self.charset)

utf8

注意:如果我修改 myENGINE_URL以使用不同的?charset=xxx,则该更改在此处反映出来。

所以现在我很难过

PyMysql 期望self.charset有一个属性encoding,但self.charset它只是一个字符串。我怎样才能改变它以达到预期的效果?

帮助?

一个有效的答案将是一个替代过程,尽管“最正确”的答案是帮助我解决字符集/编码问题。

我的主要目标只是让迁移在我的烧瓶应用程序上运行。

标签: pythonflasksqlalchemyflask-sqlalchemyalembic

解决方案


推荐阅读