在Django中,假设我有一个经常调用的函数:
def blockUser(id_to_block, user):
to_block = Usr.objects.get(pk=id_to_block)
user.blocked.add(to_block)
user.save()
user
的类型为Usr
,使用models.Model和blocked
创建的自定义类是ManyToManyField。
现在我读它的方式,Django将从数据库中提取to_block
,然后将to_block
添加到user.blocked
,两次访问数据库。由于ManyToManyField只是一个包含from_id
和to_id
的表,并且我已经知道了两个ID,我是否可以通过一次数据库访问来完成它?
我的问题是,鉴于在其他地方没有使用to_block
这一事实,Django确实会为此进行两次数据库查询吗?如果是这样,我怎么能通过一个数据库查询实现这个目标?
非常感谢!
答案 0 :(得分:0)
你可以使用Django的select_related()
。来自文档:
这是一种性能提升,导致(有时更大) 查询但意味着以后使用外键关系不会 需要数据库查询。
使用ManyToMany字段使用prefetch_related()
。与select_related()
相同的原则。来自文档:
这允许它预取多对多和多对一对象 除了外键之外,不能使用select_related来完成 和select_related支持的一对一关系。
答案 1 :(得分:0)
您无需获取to_block对象即可将其添加到被阻止的ManyToManyField。使用主键也可以。 此外,添加关系后,您无需在用户对象上调用保存。
def blockUser(id_to_block, user):
user.blocked.add(id_to_block)
然而,这会进行2次SQL查询。
如果要避免检查完整性,可以直接创建中间模型的实例。
def blockUser(id_to_block, user):
# create an instance of the intermediate model
block_entry = Usr.blocked.through(user_id=user.id, blocked_id=id_to_block)
try:
with transaction.commit_on_success():
block_entry.save()
except IntegrityError:
pass
blocked_id
可能不是正确的field_name。