SQLAlchemy: тип столбца, выведенный из внешнего ключа - PullRequest
0 голосов
/ 30 апреля 2019

Я определил таблицу связи «многие ко многим» ...

derived_prime_sport_stats = Table(
    'derived_prime_sport_stats',
    Base.metadata,
    Column(
        'prime_sport_id',
        ForeignKey('prime_sports.id', ondelete='RESTRICT'),
        primary_key=True
    ),
    Column(
        'stat_record_id',
        ForeignKey('stat_record.id', ondelete='CASCADE'),
        primary_key=True
    )
)

... запустил миграцию и пошел дальше.

Позже, осознав, что я забыл передать параметр type_ конструктору каждого из столбцов в Table, я предположил, что миграция не удалась.

Однако, mysql> show create table derived_prime_sport_stats; показывает:

CREATE TABLE `derived_prime_sport_stats` (
  `prime_sport_id` smallint(5) unsigned NOT NULL,
  `stat_record_id` bigint(20) unsigned NOT NULL,
  PRIMARY KEY (`prime_sport_id`,`stat_record_id`),
  KEY `fk_derived_prime_sport_stats_stat_record_id_stat_record` (`stat_record_id`),
  CONSTRAINT `fk_derived_prime_sport_stats_prime_sport_id_prime_sports` FOREIGN KEY (`prime_sport_id`) REFERENCES `prime_sports` (`id`),
  CONSTRAINT `fk_derived_prime_sport_stats_stat_record_id_stat_record` FOREIGN KEY (`stat_record_id`) REFERENCES `stat_record` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci 

... типы были настроены в соответствии с типом связанного столбца без явного указания.

Это поведение задокументировано, но мне не удалось найти связанный вопрос по stackoverflow, поэтому я помещаю его здесь в качестве ссылки, так как считаю, что многие, кто взаимодействует с SQLAlchemy в основном через ORM, могут не знать об этой функции. .

1 Ответ

0 голосов
/ 30 апреля 2019

Документация для type_ arg to Column указывает:

Если типом является None или он опущен, он по умолчанию будет специальный тип NullType. Если и когда эта колонка сделана для ссылки на другой столбец, использующий ForeignKey и / или ForeignKeyConstraint, тип столбца с удаленной ссылкой будет скопирован в этот столбец, в тот момент, когда внешний ключ разрешен в отношении этого удаленного Объект столбца.

Когда родительский столбец ForeignKey присоединен к его таблице, вызывается метод ForeignKey._set_table(), и в этом методе FK разрешает столбец внешней таблицы, на которую он ссылается. В этот момент, если родительский столбец FK не имеет типа, он устанавливает его из внешнего столбца. Это происходит здесь в ForeignKey._set_target_column():

# propagate TypeEngine to parent if it didn't have one
if self.parent.type._isnull:
    self.parent.type = column.type

Интересно, что в самом первом примере определения таблиц в учебник по языку выражений :

>>> from sqlalchemy import Table, Column, Integer, String, MetaData, ForeignKey
>>> metadata = MetaData()
>>> users = Table('users', metadata,
...     Column('id', Integer, primary_key=True),
...     Column('name', String),
...     Column('fullname', String),
... )

>>> addresses = Table('addresses', metadata,
...   Column('id', Integer, primary_key=True),
...   Column('user_id', None, ForeignKey('users.id')),
...   Column('email_address', String, nullable=False)
...  )

... столбец addresses.user_id имеет свой тип, явно установленный на None, чтобы использовать эту функцию, однако, кажется, нет никакого объяснения этому, пока ссылка на API для Column.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...