Sqlalchemy, наследство и отношения - PullRequest
3 голосов
/ 01 февраля 2011

У меня есть общий объект User для моего сайта, построенный как базовый класс с использованием объединенных таблиц


class User(Base):
    __tablename__ = "auth_user"

    id = Column(Integer, primary_key = True)
    username = Column(String(100), nullable = False, unique = True, index = True)
    ...
    type = Column(String(1))
    __mapper_args__ = {'polymorphic_on' : type, "extension" : HashExtension()}

У меня есть объект Staff, основанный на этом классе


class Staff(User):
    __tablename__ = "auth_staff"
    __mapper_args__ = {'polymorphic_identity' : 's'}    
    id = Column(Integer, ForeignKey('auth_user.id'), primary_key = True)

Теперь ятакже есть объект Candidate, снова полученный от пользователя


class Candidate(User):
    __tablename__ = "candidates_candidate"
    __mapper_args__ = {'polymorphic_identity' : 'c'}
    id = Column(Integer, ForeignKey('auth_user.id'), primary_key = True)
    ...
    staff_id = Column(Integer, ForeignKey("auth_user.id"), nullable = False)

    staff = relationship("Staff", backref = backref("candidates", order_by = id))

Все хорошо до конца объекта Candidate.Я хочу, чтобы он связывался с объектом Staff, но я получаю ошибки о том, что это не «первичное соединение», и меня смущает то, как это отношение должно связываться с объектом Staff - если оно связывается с объектом User по мере получения Staffот него? ....

Любые предложения будут с благодарностью приняты

~~~~~~~~~ Обновление 3 февраля ~~~~~~~~~~~~~~

Пересмотренный код - по-прежнему выдает ошибки об основном присоединении.Если я добавлю первичное соединение, оно все равно захлебнется


#!/usr/bin/env python
from sqlalchemy import Column, Integer, String, ForeignKey, Boolean
from sqlalchemy.orm import relationship, backref, sessionmaker
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import create_engine

class DomainBase(object):
    active = Column(Boolean, default = True, nullable = False)

    def __str__(self):
        return repr(self)

Base = declarative_base(cls = DomainBase)

class User(Base):
    __tablename__ = "auth_user"

    id = Column(Integer, primary_key = True)
    username = Column(String(100), nullable = False, unique = True, index = True)
    type = Column(String(1))
    __mapper_args__ = {'polymorphic_on' : type}
class Staff(User):
    __tablename__ = "auth_staff"
    __mapper_args__ = {'polymorphic_identity' : 's'}    
    id = Column(Integer, ForeignKey('auth_user.id'), primary_key = True)


class Candidate(User):
    __tablename__ = "candidates_candidate"
    __mapper_args__ = {'polymorphic_identity' : 'c'}
    id = Column(Integer, ForeignKey('auth_user.id'), primary_key = True)
    staff_id = Column(Integer, ForeignKey("auth_staff.id"), nullable = False)

    staff = relationship("Staff", backref = backref("candidates", order_by = id))


engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)

Session = sessionmaker(bind = engine, autocommit=True)
session = Session()

with session.begin():
    s = Staff(username = "DaveSmith")
    session.add_all([s])

1 Ответ

3 голосов
/ 01 февраля 2011

В вашем примере используются 2 внешних ключа для таблицы базовых классов, поэтому SQLAlchemy не может определить 1) какой внешний ключ следует использовать для соединения наследования, 2) какой внешний ключ использовать для отношений с персоналом. Вы должны указать подсказки для обоих случаев. Бывший требует 'inherit_condition' параметр в __mapper_args__ (см. Этот ответ для получения дополнительной информации ), позже требует primaryjoin=(staff_id==User.id) аргумент relationship.

Но учтите, что ваши отношения staff относятся к классу Staff, тогда как staff_id имеет внешний ключ, ссылающийся на таблицу User. Хотя у вас есть какой-то резонанс, в большинстве случаев это не очень хорошо. Изменение определения staff_id для использования ForeignKey("auth_staff.id") решит вашу проблему без других изменений.

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