簡體   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