如何使用sqla定义与关联对象的多对多关系的直接getter?

时间:2014-04-24 13:55:17

标签: orm sqlalchemy flask-sqlalchemy

我有很多关系,需要额外的字段(订单)
根据文档,我需要一个关联对象,我不能使用'辅助'。

所以这是我的代码:

# Create Many to Many table with extra field
class NodesAssets(db.Model):
    node_id = db.Column(db.Integer, db.ForeignKey('node.id'), primary_key = True)
    node = db.relationship('Node', backref=db.backref('assets_rel'))

    asset_id = db.Column(db.Integer, db.ForeignKey('asset.id'), primary_key = True)
    asset = db.relationship('Asset', backref=db.backref('nodes_rel'))

    order = db.Column('order', db.Integer)

    def __str__(self):
        return "Nodes-Assets %s-%s" % (self.node, self.asset,)


class Node(db.Model):
    id = db.Column(db.Integer, primary_key = True)
    ...

    @property
    def assets(self):
        # return assets in order

    def __str__(self):
        return self.name


class Asset(db.Model): 
    id = db.Column(db.Integer, primary_key=True)
    ...

    @property
    def nodes(self):
        # return nodes, order is not important

    def __str__(self):
        return self.name

问题1: 我如何定义从一个表到另一个表的直接连接,如果它是一个辅助表(在代码中标记为'nodes'和'assets') 对于python实例和直接查询,我都喜欢这个。 (所以混合?)

问题2: 由于它不是“次要”关系,如果在其中一个主表中删除相应的条目,我将不会删除关系表中的条目吗?

1 个答案:

答案 0 :(得分:0)

我在freenode的#sqlalchemy的agronholm的帮助下得到了答案。 (谢谢!)

SQLAlchemy已经预测了这种情况(想要关系的getter / setter) http://docs.sqlalchemy.org/en/rel_0_9/orm/extensions/associationproxy.html
甚至在我的问题的非常具体的情况下记录了一个例子:http://docs.sqlalchemy.org/en/rel_0_9/orm/extensions/associationproxy.html#simplifying-association-objects

因此,对于问题1,答案是关联代理。通过实现它,我在将关系从secondary转换为使用Association对象之前所做的查询只是不进行任何更改。要根据需要订购结果,可以使用order_by关键字。

对于问题2,还有关键字:cascade='all, delete-orphan'

以下是完整结果:

class Node(db.Model):
    id = db.Column(db.Integer, primary_key = True)
    ...

    assets = association_proxy('node_assets', 'asset')

    def __str__(self):
        return self.name


class Asset(db.Model): 
    id = db.Column(db.Integer, primary_key=True)
    ...

    nodes = association_proxy('asset_nodes', 'node')

    def __str__(self):
        return self.name


# Create Many to Many table with extra field
class NodesAssets(db.Model):
    order = db.Column('order', db.Integer)

    node_id = db.Column(db.Integer, db.ForeignKey('node.id'), primary_key = True)
    node = db.relationship(Node, backref=db.backref('node_assets', order_by=order, cascade='all, delete-orphan'))

    asset_id = db.Column(db.Integer, db.ForeignKey('asset.id'), primary_key = True)
    asset = db.relationship(Asset, backref=db.backref('asset_nodes', cascade='all, delete-orphan'))

    def __str__(self):
        return "Nodes-Assets %s-%s" % (self.node, self.asset,)

然而,并非一切顺利:(
虽然这是我想要的前端的所有内容,但是后端与flask-admin存在一些问题:

  • 我希望将Association表作为资产和节点的内联模型,但由于缺乏对具有多个主键的表的支持,目前无法实现这一点: flask-admin/issues/505
  • 忘记内联模型部分并且只有字段也不可能: flask-admin/issues/236