gpt4 book ai didi

python - flask many to many join 由 django 的 prefetch_related 完成

转载 作者:行者123 更新时间:2023-11-29 12:16:00 24 4
gpt4 key购买 nike

我在带有 Sql Alchemy ORM 的 flask 中有以下组和联系人模型

group_contact = db.Table(
'group_contact',
db.Column('group_id', db.Integer, db.ForeignKey(
'group.id')),
db.Column('contact_id', db.Integer, db.ForeignKey(
'contact.id')),
db.PrimaryKeyConstraint('group_id', 'contact_id')
)


class Group(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(100))


class Contact(db.Model):
id = db.Column(db.Integer, primary_key=True)
phone = db.Column(db.String(15), nullable=False, unique=True)
groups = db.relationship(
"Group", secondary=group_contact, backref='contacts')

现在我需要查询Contact with groups:

contacts = Contact.query.join(Group, Contact.groups).all()
for contact in contacts:
print(contact.groups)

这里的问题是当我执行上面的代码时,SQL 查询的数量随着联系人数量的增加而增加。

Django ORM 具有带有查询集的 prefetch_related(),它根据 django docs 执行以下操作.

prefetch_related, on the other hand, does a separate lookup for each relationship, and does the ‘joining’ in Python. This allows it to prefetch many-to-many and many-to-one objects, which cannot be done using select_related, in addition to the foreign key and one-to-one relationships that are supported by select_related.

现在我正尝试通过以下代码对 Sql Alchemy 做同样的事情:

contacts = Contact.query.all()     
contact_groups = group_contact.query.join(
Group
).filter(group_contact.contact_id.in_([item.id for item in contacts]))

但这给了我这个错误:

AttributeError: 'Table' object has no attribute 'query'

如何使用 SqlAlchemy 从 django 中获取类似 prefetch_related 的功能?

最佳答案

您想通过使用 relationship loading technique 告诉 SQLAlchemy 预先加载相关对象.可以告诉 SQLAlchemy 在单个查询中加载组和联系人。

对于这一个查询,您可以添加 joinedload() option (可通过 Flask-SQLAlchemy db 对象获得):

contacts = Contact.query.options(db.joinedload(Contact.groups)).all()

这会在每个匹配的联系人上预加载 Contact.groups 属性:

for contact in contacts:
# no new query issued to fetch groups, the data for the groups
# is already available
print(contact.groups)

执行的查询如下所示:

SELECT 
contact.id AS contact_id,
contact.phone AS contact_phone,
group_1.id AS group_1_id,
group_1.name AS group_1_name
FROM contact
LEFT OUTER JOIN (
group_contact AS group_contact_1
JOIN "group" AS group_1 ON group_1.id = group_contact_1.group_id
) ON contact.id = group_contact_1.contact_id

您还可以为模型上的关系设置一个默认的加载策略;要总是急切地加载组,请在关系上使用 lazy='joined':

class Contact(db.Model):
# ...
groups = db.relationship(
"Group", secondary=group_contact, backref='contacts',
lazy='joined')

关于python - flask many to many join 由 django 的 prefetch_related 完成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54054787/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com