SQLAlchemy Обработка нескольких путей в одном отношении - PullRequest
0 голосов
/ 04 октября 2018

Обратите внимание: этот вопрос связан, но отличается от другого моего в настоящее время открытого вопроса Отношение вторичного соединения SQLAlchemy для нескольких внешних ключей .

SQLAlchemyДокументация описывает обработку нескольких путей соединения в одном классе для нескольких отношений :

from sqlalchemy import Integer, ForeignKey, String, Column
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship

Base = declarative_base()

class Customer(Base):
    __tablename__ = 'customer'
    id = Column(Integer, primary_key=True)
    name = Column(String)

    billing_address_id = Column(Integer, ForeignKey("address.id"))
    shipping_address_id = Column(Integer, ForeignKey("address.id"))

    billing_address = relationship("Address")
    shipping_address = relationship("Address")

class Address(Base):
    __tablename__ = 'address'
    id = Column(Integer, primary_key=True)
    street = Column(String)
    city = Column(String)
    state = Column(String)
    zip = Column(String)

В том же разделе документация показывает три отдельных способа определенияотношения:

  1. billing_address = relationship("Address", foreign_keys=[billing_address_id])

  2. billing_address = relationship("Address", foreign_keys="[Customer.billing_address_id]")

  3. billing_address = relationship("Address", foreign_keys="Customer.billing_address_id")

Как вы можете видеть в (1) и (2), SQLAlchemy позволяет вам определять список foreign_keys.На самом деле, документация прямо заявляет:

В этом конкретном примере список не нужен ни в коем случае, так как нам нужен только один столбец: billing_address = relationship("Address", foreign_keys="Customer.billing_address_id")

Но я не могу определить, как использовать нотацию списка для указания нескольких внешних ключей в одном отношении .

Для классов

class PostVersion(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    ...
    tag_1_id = db.Column(db.Integer, db.ForeignKey("tag.id"))
    tag_2_id = db.Column(db.Integer, db.ForeignKey("tag.id"))
    tag_3_id = db.Column(db.Integer, db.ForeignKey("tag.id"))
    tag_4_id = db.Column(db.Integer, db.ForeignKey("tag.id"))
    tag_5_id = db.Column(db.Integer, db.ForeignKey("tag.id"))

class Tag(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    tag = db.Column(db.String(127))

Я пробовал все следующее:

  1. tags = db.relationship("Tag", foreign_keys=[tag_1_id, tag_2_id, tag_3_id, tag_4_id, tag_5_id]), в результате чего

sqlalchemy.exc.AmbiguousForeignKeysError: Не удалось определить условие соединения между родительскими / дочерними таблицамидля отношений AnnotationVersion.tags - существует несколько путей внешних ключей, связывающих таблицы.Укажите аргумент foreign_keys, предоставляющий список тех столбцов, которые должны считаться содержащими ссылку на внешний ключ родительской таблицы.

tags = db.relationship("Tag", foreign_keys="[tag_1_id, tag_2_id, tag_3_id, tag_4_id, tag_5_id]"), что приводит к

sqlalchemy.exc.InvalidRequestError: При инициализации mapper Mapper | AnnotationVersion | annotation_version, выражение '[tag_1_id, tag_2_id, tag_3_id, tag_4_id', tag_5, не указано)найти имя («имя 'tag_1_id' не определено»).Если это имя класса, рассмотрите возможность добавления этого отношения () к классу после определения обоих зависимых классов.

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

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

1 Ответ

0 голосов
/ 04 октября 2018

Ключ должен определить отношение в первичном соединении и указать параметр uselist.

tags = db.relationship("Tag", primaryjoin="or_(PostVersion.tag_1_id==Tag.id,"
     "PostVersion.tag_2_id==Tag.id, PostVersion.tag_3_id==Tag.id,"
     "PostVersion.tag_4_id==Tag.id, PostVersion.tag_5_id==Tag.id)",
     uselist=True)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...