2012-05-15 42 views
4

我有兩個模型 - 照片和標籤 - 它們通過ManyToManyField連接。高效刪除Django中的孤立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列表以創建交集列表?

回答

3

嘗試子查詢W /中間表

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() 
+0

美麗的解決方案 - 工程就像一個魅力!謝謝! –

+0

@Nasmon不用客氣。很高興它有助於=) – okm

+0

@Nasmon但你何時/在哪裏運行此代碼? – dialex

2

我們不得不進一步提高這個任務的表現,讓我修改OKM的解決方案了一下:

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

到的是,對數據庫的查詢變得更小更快。