2012-05-15 41 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() 

到的是,对数据库的查询变得更小更快。