SQLAlchemy,在关联代理关系中附加关联对象和额外字段

时间:2016-03-07 19:43:42

标签: python flask sqlalchemy

我在对象UserGroups之间存在多对多关系。我有一个名为Attends的关联对象,其中包含额外的字段role。我想通过使用关联代理来减少关联对象关系的详细程度。不幸的是,当我向组添加新用户时,文档不清楚如何显式添加额外字段role

小组课程

class Group(db.Model):
    __tablename__ = 'group'

    gid = db.Column(db.Integer, primary_key=True, autoincrement=True)
    oid = db.Column(db.Integer, db.ForeignKey('organization.oid'), nullable=False)
    start_time= db.Column(db.DateTime, nullable=False)
    end_time = db.Column(db.DateTime, db.CheckConstraint('end_time > start_time'), nullable=False)
    location = db.Column(db.String, nullable=False)
    description = db.Column(db.Text)

    organization = db.relationship('Organization', back_populates='groups')

    #many-to-many db.relationship with users
    registered_users = association_proxy('user_groups', 'user')

    #one to many db.relationship with tags
    tags = db.relationship('Tag', back_populates='group')

    def add_user(self, user, role):
        if not self.has_user(user):
            self.registered_users.append(Attend(user, self, role)) <-- error 
        else:
            raise ValueError('user %s already exists', user)

参加课程

class Attend(db.Model):
    __tablename__ = 'attend'
    uid = db.Column(db.Integer, db.ForeignKey('user.uid'), primary_key=True)
    gid = db.Column(db.Integer, db.ForeignKey('group.gid'), primary_key=True)
    user_role = db.Column(db.Enum(*GroupRoles.roles, name='role'))

    group = db.relationship('Group', 
        backref=db.backref('user_groups', cascade='all, delete-orphan'))

    user = db.relationship('User')

    def __init__(self, user, group, role):
        self.user = user
        self.group = group
        self.user_role = role

执行add_user方法时收到以下错误:

        def _create(self, value):
>       return self.creator(value)
E       TypeError: __init__() missing 2 required positional arguments: 'group' and 'role'

1 个答案:

答案 0 :(得分:1)

user_groups应该是Attend个对象的列表(即与Attend的关系),registered_users应该是User个对象的列表。当您追加到registered_users时,您需要让association_proxy知道如何在Attenddocs)中构建相应的user_groups对象:

registered_users = association_proxy('user_groups', 'user',
                                     creator=lambda u: Attend(user=u, user_role='some_default_role'))

注意:SQLAlchemy不知道role是什么,因此您需要提供默认值。由于user_groups关系位于Group 知道该群组应该是什么。如果您希望能够add_user(user, role),您可以直接直接附加到这段关系:

def add_user(self, user, role):
    if not self.has_user(user):
        self.user_groups.append(Attend(user=user, user_role=role))
    else:
        raise ValueError('user %s already exists', user)

请注意,这假设您将Attend类更改为使用默认构造函数。