SQLAlchemy:通过ID在多对多关系中添加子项

7 投票
1 回答
3093 浏览
提问于 2025-04-18 01:42

我想找到一种方法,可以在不先加载子对象的情况下,给一个“对象”实体添加一个“类别”子项,这样可以提高性能。

“对象”和“类别”这两个表之间是多对多的关系,具体存储在“ObjectCategory”表中。“对象”模型已经设置好了这种关系:

categories = relationship('Category', secondary = 'ObjectCategory', backref = 'objects')

现在这段代码运行得很好:

obj = models.Object.query.get(9)
cat1 = models.Category.query.get(22)
cat2 = models.Category.query.get(28)
obj.categories.extend([cat1, cat2])

但是在调试输出中,我发现创建对象和每个类别时,都会向数据库服务器发送一个单独的SELECT命令,除此之外还有一个批量INSERT命令。这在这种情况下是完全不必要的,因为我并不想操作这些类别对象。其实我只需要把合适的类别ID插入进去就可以了。

最明显的解决办法就是直接在关联表中插入记录:

db.session.add(models.ObjectCategory(oct_objID=9, oct_catID=22))
db.session.add(models.ObjectCategory(oct_objID=9, oct_catID=28))

不过这种方法看起来有点丑,不太利用SQLAlchemy的关系功能。而且每次调用add()时都会产生单独的INSERT命令,而不是像obj.categories.extend([list])那样的批量INSERT。我想可能有一种懒加载的对象模式,可以让对象只保留它的ID(未经验证),只有在需要时才加载其他字段。这样就可以在一对多或多对多关系中添加子项,而不需要向数据库发出任何SELECT请求,同时又能利用强大的ORM抽象(也就是说,把子项列表当作Python列表来处理)。

我应该如何调整我的代码,以便在使用SQLAlchemy的强大功能的同时,减少对数据库的使用呢?

1 个回答

1

你有没有为ObjectCategory表做过ORM映射?如果有的话,你可以创建并添加ObjectCategory对象:

session.add(ObjectCategory(obj_id=9, category_id=22)
session.add(ObjectCategory(obj_id=9, category_id=28)

撰写回答