Alembic-отличный способ автоматического управления вашей базой данных SQL через код Python в вашем репозитории GIT. Вместо того, чтобы вручную вносить правильные изменения вручную в базе данных каждый раз, когда вы обновляете свой код, вы можете сохранить обновления базы данных как часть вашей кодовой базы: Alembic может автоматически генерировать эти сценарии обновления, сравнивая текущую структуру вашей базы данных с тем, что они должен быть в соответствии с вашей схемой ORM (SQLALCHEMY).
Это приятно использовать, так как это означает, что вам не нужно беспокоиться о том, что ваша база данных не соответствует вашему коду, когда вы делаете развертывание. Обновление базы данных теперь можно сделать в качестве одного шага в вашем развертывании кода.
Тем не менее, одна область, где автогенератор Алембика не совсем понимается, – это то, как справиться с установкой поля из Nullable = Верно
к Nullable = Ложный
Когда в столбце уже есть нулевые значения. Автогенератор покорно создаст сценарий, который обновляет свойство столбца, которое содержит это:
def upgrade(): # ### commands auto generated by Alembic - please adjust! ### op.alter_column('table_name', 'column_name', existing_type=sa.VARCHAR(), nullable=False, schema='schema_name') # ### end Alembic commands ###
Но, поскольку он не может волновать все существующие нули в базе данных, база данных отклонит это изменение, поскольку оно оставит нули внутри столбца, который не является нулевым. Сообщение об ошибке в основном «столбец содержит нулевые значения»:
sqlalchemy.exc.ProgrammingError: (pg8000.exceptions.ProgrammingError) {'S': 'ERROR', 'V': 'ERROR', 'C': '23502', 'M': 'column "column_name" contains nu ll values', 's': 'acquire', 't': 'table_name', 'c': 'column_name', 'F': 'tablecmds.c', 'L': '4858', 'R': 'ATRewriteTable'} [SQL: ALTER TABLE schema_name.table_name ALTER COLUMN column_name SET NOT NULL]
Чтобы решить это, вы должны сначала избавиться от всех нулей, которые, если вы не хотите делать это вручную в базе данных, также может быть сделано путем редактирования сценария с автогенерированием, чтобы справиться с этим. Самый простой способ – добавить op.execute ()
Это обновит нулевые значения до чего -то другого. Что-то вроде этого:
def upgrade(): table_name = sa.sql.table("table_name", sa.Column("column_name", sa.VARCHAR()), schema="schema_name") op.execute( table_name.update() .where(table_name.c.column_name is None) .values(column_name="some_value") ) op.alter_column('table_name', 'column_name', existing_type=sa.VARCHAR(), nullable=False, schema='schema_name')
Здесь op.execute устанавливает гипотетический столбец, называемый column_name
иметь значение «some_value», если он в настоящее время нуль. Таким образом, обеспечение отсутствия значений в столбце все еще остается нулевым к тому времени, когда OP.Alter_column устанавливает Nullable
ограничение ложным.
Во всех вышеперечисленных коде это было в базе данных Postgres со схемой без декорации, называемой schema_name
Анкет Для использования схемы по умолчанию или базам данных без схемы, этого должно быть достаточно, чтобы опустить схема =
Везде это кажется.
Оригинал: “https://dev.to/meseta/alembic-setting-a-column-to-nullable-true-if-it-already-has-data-in-it-3nb7”