Flask SqlAlchemy / Alembic миграция отправляет неверный набор символов в PyMysql - PullRequest
0 голосов
/ 25 апреля 2018

Я потратил на это более 3 часов в течение 18 из 21 дня. Пожалуйста, кто-нибудь, скажите мне, что я неправильно понимаю!

TL; DR: Мой код многократно отправляет набор символов db в виде строки в PyMysql, в то время как он ожидает объект с атрибутом, называемым "encoding"

Фон

Это код Python, выполняемый в контейнере Docker. Второй контейнер содержит базу данных. Адрес базы данных хранится в переменной .env с именем ENGINE_URL:

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

Я запускаю команды Alembic и Flask-Alembic, используя команды click в CLI. Все перечисленные ниже методы используются в командах 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()

Теперь я могу открыть контейнер базы данных и использовать CLI MySql, чтобы увидеть, что все мои модели теперь преобразованы в таблицы со столбцами и связями.

Попытка 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: колба-алембик

Эта попытка обнаруживает, что я полностью переписываю свои команды main и revision, но это не так далеко, как использование 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))

Это приводит к ошибке, идентичной ошибке из моей предыдущей попытки.

Трассировка стека в обоих случаях:

(Идентичный сбой при обновлении alembic и ревизии склянки-alembic)

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, непосредственно перед ошибкой:

печать (self.charset)

utf8

Примечание: Если я изменю свой ENGINE_URL, чтобы использовать другой ?charset=xxx, это изменение будет отражено здесь.

Так что теперь я в тупике

PyMysql ожидает, что self.charset будет иметь атрибут encoding, но self.charset - это просто строка. Как я могу изменить это, чтобы вести себя как ожидалось?

Помощь

Правильный ответ будет альтернативным процессом, хотя "самый правильный" ответ будет помочь мне решить проблему с кодировкой / кодировкой.

Моя основная задача здесь - просто запустить миграцию в моем приложении для колб.

...