Дополнительные ограничения первичного ключа на объект ассоциации при указании отношения в sqlalchemy - PullRequest
0 голосов
/ 15 октября 2018

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

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

import enum

Base = declarative_base()

class Person(Base):
    __tablename__ = 'person'
    id = Column(Integer, primary_key=True)
    name = Column(Unicode)

    worksAt = relationship('Address', secondary='parelationship')
    manages = relationship('Address', secondary='parelationship')
    resides = relationship('Address', secondary='parelationship')
    ## How do I specify the additional constraint of 
    ## parelationship.relation = Relationships.resident?

class Address(Base):
    __tablename__ = 'address'
    id = Column(Integer, primary_key=True)
    name = Column(Unicode)

class Relationships(enum.Enum):
    resident = 1
    worker = 2
    manager = 3

class PersonAddressRelationship(Base):
    __tablename__ = 'parelationship'
    personId = Column(Integer, ForeignKey('person.id'), primary_key=True)
    adressID = Column(Integer, ForeignKey('address.id'), primary_key=True)
    relation = Column(Enum(Relationships), primary_key=True)

Есть ли удобный способ указать отношения worksAt, manages, resides (и в равной степени worksHere, isManagedBy и т. Д. В таблице адресов)?

1 Ответ

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

Либо определите primaryjoin или secondaryjoin с дополнительным предикатом, либо используйте производную таблицу в качестве вторичной.

Используя производную таблицу:

worksAt = relationship(
    'Address',
    secondary=lambda:
        PersonAddressRelationship.__table__.select().
            where(PersonAddressRelationship.relation == Relationships.worker).
            alias(),
    viewonly=True)

Использование primaryjoin:

manages = relationship(
    'Address', secondary='parelationship',
    primaryjoin=lambda:
        and_(Person.id == PersonAddressRelationship.personId,
             PersonAddressRelationship.relation == Relationships.manager),
    viewonly=True)

Использование secondaryjoin:

resides = relationship(
    'Address', secondary='parelationship',
    secondaryjoin=lambda:
        and_(Address.id == PersonAddressRelationship.adressID,
             PersonAddressRelationship.relation == Relationships.manager),
    viewonly=True)

Обратите внимание, что во всех примерах выражение передается как вызываемое(лямбда), так что его можно лениво оценивать во время настройки картографа.

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