2011-09-14 84 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)

得到結果。