Доступ к переменной-члену mixin (столбцу) из дочернего элемента - PullRequest
0 голосов
/ 20 сентября 2018

У меня проблемы с доступом к родительской переменной члена класса id из дочернего класса.

class BaseModel:
    id = db.Column(db.Integer, primary_key=True)

class User(db.Model, BaseModel):
    username = db.Column(db.String(35), nullable=False, unique=True)

    followed = db.relationship(
        'User',
        secondary=followers,
        primaryjoin=(followers.c.follower_id == BaseModel.id),
        secondaryjoin=(followers.c.followed_id == BaseModel.id),
        backref=db.backref('followers', lazy='dynamic'),
        lazy='dynamic')

Дает мне эту ошибку:

sqlalchemy.exc.InvalidRequestError: One or more mappers failed to initialize - can't proceed with initialization of other mappers. Triggering mapper: 'Mapper|User|user'. Original exception was: Could not locate any simple equality expressions involving locally mapped foreign key columns for primary join condition 'followers.follower_id = "<name unknown>"' on relationship User.followed.  Ensure that referencing columns are associated with a ForeignKey or ForeignKeyConstraint, or are annotated in the join condition with the foreign() annotation. To allow comparison operators other than '==', the relationship can be marked as viewonly=True.

С другой стороны

class BaseModel:
    id = db.Column(db.Integer, primary_key=True)

class User(db.Model, BaseModel):
    username = db.Column(db.String(35), nullable=False, unique=True)

    testing = BaseModel.id

Дает мне эту ошибку:

sqlalchemy.exc.InvalidRequestError: Incorrect number of values in identifier to formulate primary key for query.get(); primary key columns are 'user.testing','user.id

1 Ответ

0 голосов
/ 20 сентября 2018

Тело определения класса является его собственной областью, и введенные имена будут формировать пространство имен класса.Проблема (в вашем исходном вопросе ) с определением модели заключается в том, что имя id не было присвоено в теле класса User, поэтому объединения в определении relationship относятся кна встроенную функцию id().Вы также не можете использовать BaseModel.id, как показано в этом вопросе, потому что декларативный метакласс создаст копию его в User, поэтому он не ссылается на тот же столбец.

Решение состоит в том, чтобы использовать ленивую оценку: либо передать вызываемую, либо строку, вычисляемую на Python, в качестве соединения:

followed = db.relationship(
    'User',
    secondary=followers,
    primaryjoin='followers.c.follower_id == User.id',   # Note: the joins are
    secondaryjoin='followers.c.followed_id == User.id', # passed as strings 
    backref=db.backref('followers', lazy='dynamic'),
    lazy='dynamic')

Это работает, потому что настроены взаимосвязи мапперов мапперовпосле того, как сопоставленные классы были объявлены и используются в первый раз, если явно не сконфигурированы с использованием configure_mappers().

Обратите внимание, что вы не можете использовать обычный id в вычисляемой строке,но вместо этого он должен ссылаться на него с использованием класса User, поскольку позже он оценивается в совершенно иной области, нежели область тела, , включая имена из декларативного реестра классов и метаданные .

Последняя ошибка является результатом кода, такого как

User.query.get(some_id)

Присвоение BaseModel.id другому имени, например testing, в resul тела элемента.в вашей модели имеется составной первичный ключ, состоящий из двух целочисленных столбцов, поэтому ожидается, что Query.get() получит два набора целых чисел, а не одно целое число.

...