首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Django效率: ManyToManyField

Django效率: ManyToManyField
EN

Stack Overflow用户
提问于 2014-03-05 08:12:42
回答 2查看 285关注 0票数 2

在Django中,假设我有一个经常被调用的函数:

代码语言:javascript
复制
def blockUser(id_to_block, user):
   to_block = Usr.objects.get(pk=id_to_block)
   user.blocked.add(to_block)
   user.save()

其中,userUsr类型,是用models.Model创建的自定义类,blocked是ManyToManyField。

根据我的理解,Django将从数据库中获取to_block,然后将to_block添加到user.blocked中,访问数据库两次。既然ManyToManyField只是一个包含from_idto_id的表,而且我已经知道了这两个is,那么我是否只需访问一次DB就可以完成它?

我的问题是,鉴于to_block没有在其他地方使用,Django真的会为此进行两次DB查询吗?如果是这样,我如何通过一个数据库查询来实现这一点?

非常感谢!

EN

回答 2

Stack Overflow用户

发布于 2014-03-05 08:38:43

你可以使用Django的select_related()。从文档中:

这是一个性能助推器,它会产生(有时要大得多)更大的查询,但这意味着以后使用外键关系将不需要数据库查询

更新

对于ManyToMany字段,请使用prefetch_related()。与select_related()相同的主体。从文档中:

这允许它除了select_related支持的外键和一对一关系之外,还可以预取多对多和多对一对象,这是使用select_related无法完成的。

票数 0
EN

Stack Overflow用户

发布于 2014-03-05 14:42:12

无需获取to_block对象即可将其添加到阻塞的ManyToManyField中。使用主键也可以。此外,在添加关系之后,您不需要在用户对象上调用save。

代码语言:javascript
复制
def blockUser(id_to_block, user):
   user.blocked.add(id_to_block)

尽管如此,它还是执行了两个sql查询。

它首先检查用户是否已经阻止了user.

  • Afterwards,然后执行实际的

如果你想避免完整性检查,你可以直接创建一个中间模型的实例。

代码语言:javascript
复制
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。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22185934

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档