Я пытаюсь смоделировать очень типичную структуру разрешений, в которой модель User
(пользователь моего сайта) может быть назначена какому-то Roles
, а у каждой из этих Roles
есть несколько Permissions
.
Было бы очень полезно, если бы я мог получить relationship
от User
прямо до Permission
. Таким образом, я мог бы извлечь пользователя (экземпляр) из базы данных и просто сделать user.permissions
, чтобы получить его разрешения, поставить некоторую фильтрацию, чтобы проверить, есть ли у пользователя конкретный Permission
, предварительно загружено ... в сумме: все вкусности, которые идут с relationship
.
A viewonly
отношения будут в полном порядке. Как упоминал Майк Байер в очень похожем вопросе , я не могу писать в User.permissions
, потому что мы не знаем, какую «роль» использовать или , где вставить это.
Я создал две промежуточные таблицы:
User -- M2M --> Role(s) -- M2M --> Permission(s)
| ^
+-------- user.permissions -----------+
users_roles
для подключения user
к roles
через их первичный ключ (идентификатор)
- и
roles_permissions
для подключения каждого role
к его permissions
,
Это моя структура таблицы (упрощенная для вопроса, но даже полная версия действительно типичная и ... простая)
class User(DeclarativeBase, Mixin):
__tablename__ = 'users'
email = Column(String(25), nullable=False)
_users_roles = Table('users_roles', DeclarativeBase.metadata,
Column('user_id', ForeignKey('users.id', ...
Column('role_id', ForeignKey('roles.id', ...
PrimaryKeyConstraint('user_id', 'role_id',),
)
class Role(DeclarativeBase, Mixin):
__tablename__ = 'roles'
name = Column(Text(), nullable=False, unique=True)
users = relationship("User", secondary=_users_roles, backref="roles")
_roles_permissions = Table('roles_permissions', DeclarativeBase.metadata,
Column('role_id', ForeignKey('roles.id', ...
Column('permission_id', ForeignKey('permissions.id', ...
PrimaryKeyConstraint('role_id', 'permission_id',),
)
class Permission(DeclarativeBase, Mixin):
__tablename__ = 'permissions'
key = Column(Text, nullable=False, unique=True,)
Я видел этот другой ответ , который выглядит очень многообещающе, но, похоже, я не могу заставить его работать. Честно говоря, я пробовал много комбинаций, и я бы сказал, что самое большое, что я получил, было с этим:
permissions = relationship('Permission',
secondary="""join(User, users_roles,
User.id == users_roles.c.user_id
).join(roles_permissions,
users_roles.c.role_id == roles_permissions.c.role_id
).join(
Permission, roles_permissions.c.permission_id == Permission.id
)""",
viewonly=True,
)
Что дает мне эту ошибку:
sqlalchemy.exc.ArgumentError: Relationship User.permissions
could not determine any unambiguous local/remote column pairs
based on join condition and remote_side arguments. Consider
using the remote() annotation to accurately mark those elements
of the join condition that are on the remote side of the relationship.
Любые советы будут с благодарностью. Заранее спасибо.