2011-09-14 50 views
33

我有3个表:用户,社区,community_members(关系many2many的用户和社区)。SQLAlchemy ManyToMany辅助表与附加字段

我创建使用烧瓶SQLAlchemy的这个表:

community_members = db.Table('community_members', 
       db.Column('user_id', db.Integer, db.ForeignKey('user.id')), 
       db.Column('community_id', db.Integer, db.ForeignKey('community.id')), 
       ) 


class Community(db.Model): 
    __tablename__ = 'community' 

    id = db.Column(db.Integer, primary_key=True) 
    name = db.Column(db.String(100), nullable=False, unique=True) 
    members = db.relationship(User, secondary=community_members, 
          backref=db.backref('community_members', lazy='dynamic')) 

现在我想更多的字段添加到community_members这样的:

community_members = db.Table('community_members', 
       db.Column('id', db.Integer, primary_key=True), 
       db.Column('user_id', db.Integer, db.ForeignKey('user.id')), 
       db.Column('community_id', db.Integer, db.ForeignKey('community.id')), 
       db.Column('time_create', db.DateTime, nullable=False, default=func.now()), 
       ) 

现在在Python Shell我可以这样做:

创建社区:

> c = Community() 
> c.name = 'c1' 
> db.session.add(c) 
> db.session.commit() 

成员添加到社区:

> u1 = User.query.get(1) 
> u2 = User.query.get(2) 
> c.members.append(u1) 
> c.members.append(u2) 
> db.session.commit() 

> c.members 
[<User 1>, <User 2>] 

好吧,这个作品。

但现在我怎么能得到time_create的community_members表?

回答

46

您将不得不从使用简单的多对多关系转换为使用“关联对象”,该关联对象基本上只是使用关联表并给它一个适当的类映射。然后,您将定义一个一对多的关系,UserCommunity

class Membership(db.Model): 
    __tablename__ = 'community_members' 

    id = db.Column('id', db.Integer, primary_key=True) 
    user_id = db.Column(db.Integer, db.ForeignKey('user.id')) 
    community_id = db.Column(db.Integer, db.ForeignKey('community.id')) 
    time_create = db.Column(db.DateTime, nullable=False, default=func.now()) 

    community = db.relationship(Community, backref="memberships") 
    user = db.relationship(User, backref="memberships") 


class Community(db.Model): 
    __tablename__ = 'community' 

    id = db.Column(db.Integer, primary_key=True) 
    name = db.Column(db.String(100), nullable=False, unique=True) 

但是你可能只是偶尔有兴趣在创建时间;你想要旧的关系回来!好吧,你不想两次设置relationship;因为sqlalchemy会认为你想要两个协会;这必定意味着不同的东西!您可以通过在association proxy.

from sqlalchemy.ext.associationproxy import association_proxy 

Community.members = association_proxy("memberships", "user") 
User.communities = association_proxy("memberships", "community") 
+6

我用你的解决方案,它的工作,但我仍然有一个问题。是否有可能Community.members(添加了关联代理)返回一个AppenderBaseQuery,我可以添加更多的过滤器,例如Community.members.filter_by(...)?我习惯在关系声明中使用懒惰=动态的简单的多对多关系来做到这一点,但是在将关联表映射到关联表之后,似乎我不能再这样做了。 – stefanobaldo

+0

你有没有发现解决方案@stefanobaldo - 如果你真的有用! – pip

0

将做到这一点。如果你只需要查询community_memberscommunity表由已知USER_ID(如USER_ID = 2),在SQLAlchemy中,你可以执行:

session.query(community_members.c.time_create, Community.name).filter(community_members.c.user_id==2)

得到结果。