繁体   English   中英

Django:select_related和GenericRelation

[英]Django: select_related and GenericRelation

select_related是否适用于GenericRelation关系,还是有合理的替代方案? 目前Django正在为我的查询集中的每个项目执行单独的sql调用,并且我想避免使用像select_related这样的东西。

class Claim(models.Model):
    proof = generic.GenericRelation(Proof)


class Proof(models.Model):
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    content_object = generic.GenericForeignKey('content_type', 'object_id')

我正在选择一堆声明,我希望将相关的Proofs拉入而不是单独查询。

没有内置的方法来做到这一点。 但我发布了一种在我的博客上模拟一般关系上的 select_related的技术。


博客内容汇总:

我们可以使用Django的_content_object_cache字段来创建我们自己的select_related用于泛型关系。

generics = {}
for item in queryset:
    generics.setdefault(item.content_type_id, set()).add(item.object_id)

content_types = ContentType.objects.in_bulk(generics.keys())

relations = {}
for ct, fk_list in generics.items():
    ct_model = content_types[ct].model_class()
    relations[ct] = ct_model.objects.in_bulk(list(fk_list))

for item in queryset:
    setattr(item, '_content_object_cache', 
            relations[item.content_type_id][item.object_id])

在这里,我们获取查询集中关系使用的所有不同内容类型,以及每个内容的不同对象ID的集合,然后使用内置的in_bulk管理器方法一次性获取所有内容类型 - 使用ID键入的字典。 然后,我们为每个内容类型执行一次查询,再次使用in_bulk,以获取所有实际对象。

最后,我们只需将相关对象设置为源项的_content_object_cache字段即可。 我们这样做的原因是,如果您直接调用x.content_object,这是Django将检查的属性,并在必要时填充。 通过预先填充它,我们确保Django永远不需要调用单独的查找 - 实际上我们正在做的是为泛型关系实现一种select_related()。

看起来像select_related和GRs不能一起工作 我想你可以为Claim写一些访问器,通过相同的查询获取它们。 这篇文章为您提供了一些关于原始SQL的指针 ,以便在需要时获取通用对象

您可以使用.extra()函数手动提取字段:

Claims.filter(proof__filteryouwant=valueyouwant).extra(select={'field_to_pull':'proof_proof.field_to_pull'})

.filter()将执行连接,.extra()将提取字段。 proof_proof是Proof模型的SQL表名。 如果您需要多个字段,请在字典中指定每个字段。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM