在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的表,而且我已经知道了这两个is,那么我是否只需访问一次DB就可以完成它?
我的问题是,鉴于to_block没有在其他地方使用,Django真的会为此进行两次DB查询吗?如果是这样,我如何通过一个数据库查询来实现这一点?
非常感谢!
发布于 2014-03-05 08:38:43
你可以使用Django的select_related()。从文档中:
这是一个性能助推器,它会产生(有时要大得多)更大的查询,但这意味着以后使用外键关系将不需要数据库查询。
更新
对于ManyToMany字段,请使用prefetch_related()。与select_related()相同的主体。从文档中:
这允许它除了select_related支持的外键和一对一关系之外,还可以预取多对多和多对一对象,这是使用select_related无法完成的。
发布于 2014-03-05 14:42:12
无需获取to_block对象即可将其添加到阻塞的ManyToManyField中。使用主键也可以。此外,在添加关系之后,您不需要在用户对象上调用save。
def blockUser(id_to_block, user):
user.blocked.add(id_to_block)尽管如此,它还是执行了两个sql查询。
它首先检查用户是否已经阻止了user.
如果你想避免完整性检查,你可以直接创建一个中间模型的实例。
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:
passblocked_id可能不是正确的field_name。
https://stackoverflow.com/questions/22185934
复制相似问题