【问题标题】:How can SQLAlchemy association_proxy be used bi-directionally?SQLAlchemy association_proxy 如何双向使用?
【发布时间】:2014-02-01 18:41:18
【问题描述】:

我正在使用 Flask-SQLAlchemy 使用 Association Objectsassociation_proxy 创建多对多关系,但我遇到了一个问题:当我使用 association_proxy 时,我可以设置它这样,当我将新实例附加到关系的一侧时,将创建关联对象,但如果我尝试从关系的另一侧添加实例,则关联对象构造函数将不会传递正确的实例.

这是一个简化的示例,其中Club 有很多PeoplePeople 有很多Club,关联对象是Membership

class Club(db.Model):
    __tablename__ = 'clubs'

    id = db.Column(db.Integer, db.Sequence('clubs_id_seq'), autoincrement=True, primary_key=True)
    name = db.Column(db.String(255))
    memberships = db.relationship('Membership', backref='club')
    members = association_proxy('memberships', 'club') # Can I pass a Person instance to Membership here? 
    created_at = db.Column('created_at', db.DateTime, default=datetime.datetime.now())

    def __init__(self, name):
        self.name = name

class Person(db.Model):
    __tablename__ = 'people'

    id = db.Column(db.Integer, db.Sequence('people_id_seq'), autoincrement=True, primary_key=True)
    name = db.Column(db.String(255))
    memberships = db.relationship('Membership', backref='person')
    clubs = association_proxy('memberships', 'club')
    created_at = db.Column('created_at', db.DateTime, default=datetime.datetime.now())

    def __init__(self, name):
        self.name = name

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

    person_id = db.Column('person_id', db.Integer, db.ForeignKey('people.id'), primary_key=True)
    club_id = db.Column('club_id', db.Integer, db.ForeignKey('clubs.id'), primary_key=True)
    club = db.relationship('Club', backref='membership')
    joined_at = db.Column('joined_at', db.DateTime, default=datetime.datetime.now())

    def __init__(self, club):
        self.club = club

我使用association_proxy 不仅是因为ClubPerson 之间的连接很重要;如果需要,我还希望能够检索Membershipjoined_at 属性。不过,在大多数情况下,我只会查询并附加到 .membersClub.clubsPerson。在这个例子中,我可以通过调用person_instance.clubs.append(club_instance) 来创建一个新的Membership,但是由于Membership 的构造函数只能接受一个参数,如果我要向后工作,我该如何调用club_instance.members.append(person_instance)?我可能会遍历club_instance.members,这似乎很糟糕,但必须记住不要append()。我错过了什么吗?

【问题讨论】:

    标签: python sqlalchemy flask-sqlalchemy


    【解决方案1】:

    this Google Groups discussion 找到我的答案。以下是相关部分:

    class DossierTarife(Base):
        __tablename__ = 'tarifer_dossier'
        IdDossier = Column(Integer, ForeignKey('dossier.IdDossier'), primary_key=True)
        IdAt = Column(Integer, ForeignKey('article_tarife.IdAt'), primary_key=True)
    
        dossier = relationship(Dossier, backref=backref("tarifer_dossier", cascade="all, delete-orphan"))
        article_tarife = relationship(ArticleTarife, backref=backref("tarifer_dossier"))
    
    class Dossier(Base):
        __tablename__ = 'dossier'
        IdDossier = Column('IdDossier', Integer, primary_key=True)
       ...
    
    class ArticleTarife(Base):
        __tablename__ = 'article_tarife'
        IdAt = Column('IdAt', Integer, primary_key=True)
       ...
    
    Dossier.LesTar = association_proxy("tarifer_dossier", "article_tarife", creator=lambda art:DossierTarife(article_tarife=art))
    ArticleTarife.LesTar = association_proxy("tarifer_dossier", "dossier", creator=lambda dos:DossierTarife(dossier=dos))
    

    我直接在类定义中分配了我的association_proxy,而不是像上面那样事后才分配,这也很有效。

    this SO answer 描述了如何正确删除关联对象行也很有帮助:

    user = relationship(User, backref=backref('user_to_groups', cascade='all, delete-orphan'))
    group = relationship(Group, backref=backref('group_to_user', cascade='all, delete-orphan'))
    

    【讨论】:

      猜你喜欢
      • 2014-07-28
      • 1970-01-01
      • 2011-06-02
      • 2016-11-12
      • 2012-10-11
      • 2013-08-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多