Полный новичок в Alembic, SQLAlchemy и Python. Я дошел до того, что Alembic сравнивает существующие объекты в базе данных с декларативными классами, которые я создал, и есть один надоедливый индекс (для внешнего ключа), который Alembic отказывается оставлять на месте при моей первоначальной миграции.

Я совершенно не понимаю, почему миграция постоянно пытается отбросить и воссоздать этот индекс, который, если я оставлю миграцию, держу пари, все равно потерпит неудачу. Кроме того, если я не согласовываю класс с базой данных, это, вероятно, будет появляться каждый раз, когда я автоматически создаю миграции.

Вот подходящая часть того, что находится в методе upgrade:

op.drop_index(
    'vndr_prod_tp_cat_category_fk_idx',
    table_name='vendor_product_types_magento_categories'
)

В методе downgrade:

op.create_index(  
    'vndr_prod_tp_cat_category_fk_idx',
    'vendor_product_types_magento_categories',
    ['magento_category_id'],
    unique=False
)

... вот DDL для таблицы в том виде, в каком он существует в MySQL:

CREATE TABLE `vendor_product_types_magento_categories` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `vendor_product_type_id` bigint(20) unsigned NOT NULL,
  `magento_category_id` bigint(20) unsigned NOT NULL,
  `sequence` tinyint(3) unsigned NOT NULL,
  `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `updated_at` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  UNIQUE KEY `vendor_product_types_magento_categories_uq` (`vendor_product_type_id`,`magento_category_id`,`sequence`),
  KEY `vndr_prod_tp_cat_category_fk_idx` (`magento_category_id`),
  CONSTRAINT `vndr_prod_tp_cat_magento_category_fk` FOREIGN KEY (`magento_category_id`) REFERENCES `magento_categories` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
  CONSTRAINT `vndr_prod_tp_cat_product_type_fk` FOREIGN KEY (`vendor_product_type_id`) REFERENCES `vendor_product_types` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=101 DEFAULT CHARSET=utf8

... и вот класс, который я написал:

from sqlalchemy import Column, Integer, UniqueConstraint, ForeignKeyConstraint, Index
from sqlalchemy.dialects.mysql import TIMESTAMP
from sqlalchemy.sql import text
from .base import Base


class VendorProductTypesMagentoCategories(Base):
    __tablename__ = 'vendor_product_types_magento_categories'

    id = Column(Integer, primary_key=True)
    vendor_product_type_id = Column(
        Integer,
        nullable=False
    )
    magento_category_id = Column(
        Integer,
        nullable=False
    )
    sequence = Column(Integer, nullable=False)
    created_at = Column(TIMESTAMP, server_default=text('CURRENT_TIMESTAMP'), nullable=False)
    updated_at = Column(
        TIMESTAMP,
        server_default=text('NULL ON UPDATE CURRENT_TIMESTAMP'),
        nullable=True
    )

    __table_args__ = (
        UniqueConstraint(
            'vendor_product_type_id',
            'magento_category_id',
            'sequence',
            name='vendor_product_types_magento_categories_uq'
        ),
        ForeignKeyConstraint(
            ('vendor_product_type_id',),
            ('vendor_product_types.id',),
            name='vndr_prod_tp_cat_product_type_fk'
        ),
        ForeignKeyConstraint(
            ('magento_category_id',),
            ('magento_categories.id',),
            name='vndr_prod_tp_cat_category_fk_idx'
        ),
    )

    def __repr__(self):
        return '<VendorProductTypesMagentoCategories (id={}, vendor_name={}, product_type={})>'.format(
            self.id,
            self.vendor_name,
            self.product_type
        )
0
smoopins 14 Май 2021 в 02:11

1 ответ

Лучший ответ

Вы определяете внешний ключ продукта в коде Python как

    ForeignKeyConstraint(
        ('magento_category_id',),
        ('magento_categories.id',),
        name='vndr_prod_tp_cat_category_fk_idx'
    )

Здесь вы используете vndr_prod_tp_cat_category_fk_idx как имя ограничения внешнего ключа, а не как имя базового индекса, что объясняет, почему sqlalchemy хочет удалить индекс.

Вы должны использовать vndr_prod_tp_cat_product_type_fk в качестве имени внешнего ключа и иметь отдельную конструкцию Index() с vndr_prod_tp_cat_category_fk_idx в качестве имени для создания индекса.

0
Shadow 13 Май 2021 в 23:55