2010-05-30 1 views
7

select_related가 GenericRelation 관계에 대해 작동합니까 아니면 합리적인 대안이 있습니까? Django가 쿼리 세트의 각 항목에 대해 개별 sql 호출을하는 순간 select_related와 같은 것을 사용하지 않도록하고 싶습니다.장고 : select_related 및 GenericRelation

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') 

클레임을 여러 개 선택하고 있으며 개별적으로 쿼리하는 대신 관련 교정본을 가져오고 싶습니다.

답변

16

이 작업을 수행 할 수있는 기본 방법이 없습니다. 그러나 select_related을 일반 관계 on my blog에 시뮬레이트하는 기술을 게시했습니다.


블로그 내용 요약 :

우리는 기본적으로 일반적인 관계에 대한 우리 자신의 select_related을 만들 장고의 _content_object_cache 필드를 사용할 수 있습니다. 다음 사용

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가 개별적으로 룩업을 호출 할 필요가 없음을 보장합니다. 실제로 우리가하는 일은 일반적인 관계에 대해 select_related()를 구현하는 것입니다.

3

수동으로 필드를 추출() 함수를 .extra 사용할 수 있습니다

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

.filter()을 조인 할 것이라고 .extra는() 필드를 가져옵니다. proof_proof은 Proof 모델의 SQL 테이블 이름입니다. 필드가 두 개 이상 필요한 경우 해당 필드를 각각 사전에 지정하십시오.