SQLAlchemy, отношение один к одному на одной и той же таблице - PullRequest
1 голос
/ 21 февраля 2012

У меня есть класс Location.Местоположения могут иметь «счет на адреса» по умолчанию, которые также являются местоположениями.Поля, с которыми я работаю, это bill_to_id и bill_to в классе CustomerLocation.Я включил родительский класс хорошо для полноты.Как установить одно местоположение в качестве счета для другого местоположения?Отношения должны быть взаимно-однозначными (местоположение будет иметь только один счет-фактуру).Обратной ссылки не требуется.

TIA

class Location(DeclarativeBase,TimeUserMixin):
    __tablename__ = 'locations'

    location_id = Column(Integer,primary_key=True,autoincrement=True)
    location_code = Column(Unicode(10))
    name = Column(Unicode(100))
    address_one = Column(Unicode(100))
    address_two = Column(Unicode(100))
    address_three = Column(Unicode(100))
    city = Column(Unicode(100))
    state_id = Column(Integer,ForeignKey('states.state_id'))
    state_relate = relation('State')
    zip_code = Column(Unicode(100))
    phone = Column(Unicode(100))
    fax = Column(Unicode(100))
    country_id = Column(Integer,ForeignKey('countries.country_id'))
    country_relate = relation('Country')
    contact = Column(Unicode(100))
    location_type = Column('type',Unicode(50))

    __mapper_args__ = {'polymorphic_on':location_type}

class CustomerLocation(Location):
    __mapper_args__ = {'polymorphic_identity':'customer'}
    customer_id = Column(Integer,ForeignKey('customers.customer_id',
                                            use_alter=True,name='fk_customer_id'))
    customer = relation('Customer',
                        backref=backref('locations'),
                        primaryjoin='Customer.customer_id == CustomerLocation.customer_id')
    tbred_ship_code = Column(Unicode(6))
    tbred_bill_to = Column(Unicode(6))
    ship_method_id = Column(Integer,ForeignKey('ship_methods.ship_method_id'))
    ship_method = relation('ShipMethod',primaryjoin='ShipMethod.ship_method_id == CustomerLocation.ship_method_id')
    residential = Column(Boolean,default=False,nullable=False)
    free_shipping = Column(Boolean,default=False,nullable=False)
    collect = Column(Boolean,default=False,nullable=False)
    third_party = Column(Boolean,default=False,nullable=False)
    shipping_account = Column(Unicode(50))
    bill_to_id = Column(Integer,ForeignKey('locations.location_id'))
    bill_to = relation('CustomerLocation',remote_side=['locations.location_id'])

1 Ответ

2 голосов
/ 21 февраля 2012

См. Мой ответ на связанный вопрос . Вы можете иметь самоссылочные отношения в декларативном виде, объявив в таблице самоссылающийся внешний ключ и либо «исправляя обезьяны» класс сразу после его объявления, либо указав имена внешних столбцов в виде строк, а не полей класса. Пример:

class Employee(Base):
  __tablename__ = 'employee'
  id = Column(Integer, primary_key=True)
  name = Column(String(64), nullable=False)
Employee.manager_id = Column(Integer, ForeignKey(Employee.id))
Employee.manager = relationship(Employee, backref='subordinates',
    remote_side=Employee.id)

Я успешно использовал этот метод, который дает вам оба направления отношений между родителем и потомком (где один родитель может иметь несколько дочерних записей). Если вы пропустите аргумент backref, он может работать, а может и не работать. Вы всегда можете просто использовать только одно направление отношений в вашем приложении.

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