Flask和SQLalchemy追加关系,而不是每次都加载对象

时间:2018-01-18 11:34:43

标签: python sqlalchemy

我正在使用python flask和api休息SQLalchemy。我有两个班级父母和孩子:

Class Parent(db.Model):
    id = db.Column(db.Integer, nullable=False, autoincrement=True, primary_key=True)
    name = db.Column(db.String, nullable=False)

    children = relationship('Child',
                                secondary=parent_has_children,
                                back_populates='parents'
                                )


Class Child(db.Model):
    id = db.Column(db.Integer, nullable=False, autoincrement=True, primary_key=True)
    name = db.Column(db.String, nullable=False)

    parents = relationship('Parent',
                                secondary=parent_has_children,
                                back_populates='children'
                                )

   parent_has_children = db.Table('parent_has_children', db.metadata,
                            db.Column('parent_id', db.Integer, ForeignKey('Parent.id')),
                            db.Column('child_id', db.Integer, ForeignKey('Child.id'))
                            )

我有很多关系,因此我使用的是辅助表。让我说我有一条接收child_id和parent_id并建立关系的路线:

@app.route('/buildrelationship', methods=['POST'])
def buildrelationship():
    child_id= request.json['student_id']
    parent_id = request.json['parent_id']
    child = Child.query.get(child_id)
    parent = Parent.query.get(parent_id)
    parent.children.append(child)
    db.session.commit()

这种方式我添加了一个孩子的父亲之间的关系,但我必须首先从数据库中获取父和子,然后添加关系。 request.json可能有一个子列表要附加到父级或父级列表o父级要附加到特定子级。在这种情况下,我必须查询列表长度的次数,以获取父级或子级,然后附加关系。是否有更好的方法来追加关系,而不是每次都加载父对象和子对象?

1 个答案:

答案 0 :(得分:2)

可以减少查询,但是您希望尽可能地依赖ORM。如果您没有执行查询以将POSTed数据解析为Child或Parent对象,而是直接插入到M2M表中,则会显示id - 您可能会对数据库的完整性造成一些麻烦。

您只需触发一个更新查询 - 如果您首先在您的孩子列表中迭代一次,那么您最终可能会获得[Flags] public enum ParallelScope { None, // the test may not be run in parallel with other tests Self, // the test itself may be run in parallel with other tests Children, // child tests may be run in parallel with one another Fixtures // fixtures may be run in parallel with one another } 列表,那么您可以children = [Child<1>, Child<2>, Child<3>]

如果,你真的每个POST处理数十/数十万个子对象,时间,内存等实际上是一个问题,你可以翻转批量加载数据,几乎完全跳过ORM层和所有安全功能它可以帮助您。

首先,您需要获取当前子对象的列表,这样您才能确保不会导致完整性错误(再次,安全手套已关闭,如果您正在做的话,您会很奇怪这没有充分的理由)。

Parent.children.append(children)

接下来,您将获得已发布的子ID ID列表:

existing = {x.id for x in Child.query.all()}
# lets say: existing = {1,3,4,5,6}

因此,我们现在可以过滤实际需要插入的内容,清理可能导致我们麻烦的任何事情:

target = request.json['student_id']
# lets say target = [1,2,3,3,3]

构建字典列表以表示我们的M2M表数据:

children_to_insert = {x for x in target if x in existing}
# active_children = {1,3}

我已经跳过了你想要的所有其他完整性检查(父母是否存在?它是否已经有了孩子?)但是你希望得到这一点,即只使用ORM并且不要试图四处走动它没有很好的理由回来了。