2011-09-14 42 views
33

Tôi có 3 bảng: Người dùng, Cộng đồng, community_members (cho mối quan hệ nhiều2many người dùng và cộng đồng).SQLAlchemy Bảng phụ ManyToMany với các trường bổ sung

tôi có thể tạo bảng này sử dụng Flask-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')) 

Bây giờ tôi muốn thêm trường bổ sung để community_members như thế này:

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()), 
       ) 

Và bây giờ trong vỏ python tôi có thể làm điều này:

tạo cộng đồng:

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

thêm thành viên vào cộng đồng:

> 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>] 

Ok, công trình này.

Nhưng bây giờ tôi có thể nhận time_create bảng community_members như thế nào?

Trả lời

46

Bạn sẽ phải chuyển từ sử dụng một mối quan hệ đồng bộ, nhiều-nhiều để sử dụng "Đối tượng liên kết", về cơ bản chỉ lấy bảng liên kết và cho nó ánh xạ lớp thích hợp. Sau đó bạn sẽ xác định một-nhiều mối quan hệ để 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) 

Nhưng bạn có thể chỉ thỉnh thoảng mới được quan tâm trong thời gian tạo; bạn muốn mối quan hệ cũ trở lại! tốt, bạn không muốn thiết lập relationship hai lần; bởi vì sqlalchemy sẽ nghĩ rằng bạn bằng cách nào đó muốn hai liên kết; điều đó phải có ý nghĩa khác! Bạn có thể làm điều này bằng cách thêm vào một association proxy.

from sqlalchemy.ext.associationproxy import association_proxy 

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

Tôi đã sử dụng giải pháp của bạn và nó đã hoạt động nhưng tôi vẫn gặp sự cố. Có thể là Community.members (được thêm vào với proxy kết hợp) trả về một AppenderBaseQuery mà tôi có thể thêm bộ lọc khác, ví dụ: Community.members.filter_by (...)? Tôi đã từng làm điều đó với mối quan hệ nhiều - nhiều, sử dụng lazy = dynamic trong khai báo quan hệ, nhưng sau khi đưa ra một ánh xạ lớp tới bảng kết hợp, có vẻ như tôi không thể làm điều đó nữa. – stefanobaldo

+0

Bạn đã bao giờ khám phá ra giải pháp @stefanobaldo - sẽ thực sự hữu ích nếu bạn đã làm! – pip

0

Nếu bạn chỉ cần truy vấn community_memberscommunity bảng bằng một user_id nổi tiếng (như user_id = 2), Trong SQLAlchemy, bạn có thể thực hiện:

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

để nhận kết quả.

Các vấn đề liên quan