Как правильно определить обратные ссылки SQLAlchemy, чтобы они могли быть отражены? - PullRequest
0 голосов
/ 22 октября 2018

Предположим, у нас есть следующий код в некотором файле Models.py:

class Person(db.Model):
    __tablename__ = 'Persons'
    ID = db.Column(db.Integer, primary_key=True, nullable=False)
    Name = db.Column(db.String(255), nullable=False)

class House(db.Model):
    __tablename__ = 'Houses'
    ID = db.Column(db.Integer,primary_key=True,nullable=False)
    OwnerID = db.Column(db.Integer, nullable=False)
    TenantID = db.Column(db.Integer, nullable=False)

    __table_args__ = (
        db.ForeignKeyConstraint(
            ['OwnerID'],
            ['Persons.ID'],
        ),
        db.ForeignKeyConstraint(
            ['TenantID'],
            ['Persons.ID'],
        ),
    )

    OwnerBackref = db.relationship('Person', backref='OwnerBackref', lazy=True, foreign_keys=[OwnerID])
    TenantBackref = db.relationship('Person', backref='TenantBackref', lazy=True, foreign_keys=[TenantID])

И мы хотим отразить эти модели, используя базу Autop, поэтому у нас есть этот код в другом модуле с именем Database.py:

Base = automap_base()
engine = create_engine(DB_CONNECTION, pool_size=10, max_overflow=20)
db_session = scoped_session(sessionmaker(autocommit=False, autoflush=False, bind=engine))
Base.prepare(engine, reflect=True)
Person = Base.classes.Persons
House = Base.classes.Houses

Теперь, когда я импортирую House в какой-то другой модуль, я хочу сделать это:

h = db_session.query(House).first()
print(h.OwnerBackref.Name)
print(h.TenantBackref.Name)

Но вместо этого я получаю сообщение о том, что эти 2 backrefs делаютне существует, и вместо этого к моему объекту Дома добавляется поле с именем «лица», но проблема здесь в том, что он связывает только 1 (либо Арендатор, либо Владелец).Под этим я подразумеваю, что если я сделаю это:

print(h.persons.Name)

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

Итак, мой вопрос заключается в том, как я могу использовать созданные мной обратные ссылки для доступа к желаемой информации? Я что-то здесь не так делаю?

1 Ответ

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

Ошибка в вашем коде заключается в том, что вы используете foreign_keys= для определения взаимосвязи между таблицами, но передаете имя локального ключа, а не имя внешнего ключа функции.Для вашего кода вы не можете использовать foreign_keys= для определения отношений в модели Дома, так как существует только один возможный внешний ключ Person.ID, но два возможных локальных ключа House.OwnerID и House.TenantID.Вместо этого следует использовать аргумент primaryjoin=.

class Person(db.Model):
    __tablename__ = 'Persons'
    ID = db.Column(db.Integer, primary_key=True)
    Name = db.Column(db.String(255), nullable=False)

class House(db.Model):
    __tablename__ = 'Houses'
    ID = db.Column(db.Integer,primary_key=True)
    OwnerID = db.Column(db.Integer, db.ForeignKey('Persons.ID'), nullable=False)
    TenantID = db.Column(db.Integer, db.ForeignKey('Persons.ID'), nullable=False)

    Owner = db.relationship('Person', backref='HousesOwned', primaryjoin='House.OwnerID == Person.ID')
    Tenant = db.relationship('Person', backref='HousesOccupied', primaryjoin='House.TenantID == Person.ID')

Если вы поместите операторы отношений в модель Person, а не в модель House, тогда вы можете использовать либо foreign_keys=, либо primaryjoin=определить отношения.Следующий код приведет к точно таким же отношениям, как и в предыдущем коде.

class Person(db.Model):
    __tablename__ = 'Persons'
    ID = db.Column(db.Integer, primary_key=True)
    Name = db.Column(db.String(255), nullable=False)

    HousesOwned = db.relationship('House', backref='Owner', foreign_keys='[House.OwnerID]')
    HousesOccupied = db.relationship('House', backref='Tenant', foreign_keys='[House.TenantID]')


class House(db.Model):
    __tablename__ = 'Houses'
    ID = db.Column(db.Integer,primary_key=True)
    OwnerID = db.Column(db.Integer, db.ForeignKey('Persons.ID'), nullable=False)
    TenantID = db.Column(db.Integer, db.ForeignKey('Persons.ID'), nullable=False)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...