SQLAlchemy lazy=dynamic с m2m връзка, използваща модел на асоцииран обект

Имам проста m2m връзка между users и roles таблици:

users_roles = db.Table('users_roles',
    db.Column('user_id', db.Integer, db.ForeignKey('users.id')),
    db.Column('role_id', db.Integer, db.ForeignKey('roles.id')),
    db.Column('is_primary', db.Boolean)
)

class User(db.Model):
    __tablename__ = 'users'
    id = db.Column('id', db.Integer, primary_key=True)
    roles = db.relationship('Role', secondary=users_roles, lazy='dynamic', backref=db.backref('users', lazy='dynamic'))

class Role(db.Model):
    __tablename__ = 'roles'
    id = db.Column('id', db.Integer, primary_key=True)
    users = db.relationship('User', secondary=users_roles, lazy='dynamic', backref=db.backref('roles', lazy='dynamic'))

За да добавя запис към таблицата users_roles, трябва да направя нещо подобно:

role = Role.get(1)
user = User()
user.roles.append(role)
db.session.add(user)
db.session.commit()

Това е добре, но имам колона с име is_primary в таблицата users_roles, която също трябва да бъде попълнена.

Промених кода си, за да използвам Обект на асоцииране както е описано в документацията на SQLAlchemy.

Сега кодът ми изглежда така:

class User(db.Model):
    __tablename__ = 'users'
    id = db.Column('id', db.Integer, primary_key=True)

class Role(db.Model):
    __tablename__ = 'roles'
    id = db.Column('id', db.Integer, primary_key=True)

class UserRole(db.Model):
    __tablename__ = 'users_roles'
    user_id = db.Column(db.Integer, db.ForeignKey('users.id'), primary_key=True)
    role_id = db.Column(db.Integer, db.ForeignKey('roles.id'), primary_key=True)
    is_primary = db.Column(db.Boolean)

    user = db.relationship(User, backref="users_roles")
    role = db.relationship(Role, backref="users_roles")

User.roles = association_proxy("users_roles", "role")
Role.users = association_proxy("users_roles", "user")

Работи добре, но все още имам проблем. Възможно ли е User.roles (добавен с проксито за асоцииране) да връща AppenderBaseQuery, че мога да добавя още филтри, напр. User.query.get(1).roles.filter_by(...)? Бях свикнал да правя това с обикновената връзка много към много, използвайки lazy=dynamic в декларацията на връзката, но след като дадох картографиране на клас към таблицата за асоцииране, изглежда, че вече не мога да го правя. Има ли начин да се постигне това?

@IfLoop Следвах препоръката ви в тази публикация. Вашата помощ ще бъде много ценена.


person stefanobaldo    schedule 31.01.2015    source източник


Отговори (1)


Е, в крайна сметка филтрирах roles с помощта на следния код:

roles = Role.query.filter_by(...).join(UserRole).join(User).filter_by(id=1)

Все още искам да мога да направя нещо подобно:

roles = User.query.get(1).roles.filter_by(...).all()

Както и да е, ако не получа отговор до няколко дни, ще приема това като отговор.

person stefanobaldo    schedule 01.02.2015