2012-05-15 5 views
4

두 개의 모델 (사진 및 태그)이 ManyToManyField를 통해 연결되어 있습니다.장고의 고아 m2m 객체/태그를 효율적으로 삭제

class Photo(models.Model): 
    tags = models.ManyToManyField(Tag) 

class Tag(models.Model): 
    lang = models.CharField(max_length=2) 
    name_es = models.CharField(max_length=40) 
    name_en = models.CharField(max_length=40) 

가끔씩 사진이 더 이상 참조하지 않는 고아 태그가 표시됩니다. 이러한 태그를 효과적으로 삭제할 수 있습니까? 나는이 대답에 대해 알고 : Django: delete M2M orphan entries?

그리고 우리의 솔루션은 순간 다음과 같습니다 : 데이터베이스가 증가함에 따라,

for tag in Tag.objects.all(): 
    if not tag.photo_set.select_related(): tag.delete() 

그러나이,이 스크립트의 실행이 참혹하게 높은 - P되고 것은 거기 태그 테이블에서 모든 태그 ID의 목록을 얻은 다음 다 대 다 테이블의 모든 태그 ID 목록을 가져 와서 교차 목록을 만드는 효율적인 방법? 중간 테이블

qs = Tag.objects.exclude(pk__in=Book.tags.through.objects.values('tag')) 

# then you could 
qs.delete() 

# or if you need to trigger signal per item 
for x in qs: 
    x.delete() 

답변

3

시도 서브 쿼리가함으로써

all_tag_pks = Tag.objects.values_list('pk', flat=True) 
    used_tag_pks = Photo.tags.through.objects.values_list('tag', flat=True) 
    Tag.objects.filter(pk__in=list(set(all_tag_pks) - set(used_tag_pks))).delete() 

을의 데이터베이스에 대한 쿼리가 훨씬 작고 빠릅니다.

+0

아름다운 솔루션 - 매력처럼 작동합니다! 감사! –

+0

@Nasmon 여러분을 환영합니다. 다행스럽게도 =) – okm

+0

@Nasmon 그러나이 코드를 언제 어디서 실행합니까? – dialex

2

/우리는 더이 작업의 성능을 향상시킬 수 있었다, 그래서 나는 조금 OKM의 솔루션 수정 승