Django:通过外键查找所有反向引用

时间:2015-03-20 02:27:58

标签: python django model-view-controller model

好吧,现在我正在使用Django 1.6 +

我有一个模特:

class FileReference(models.Model):
    # some data fields
    # ...
    pass

class Person(models.Model):
    avatar = models.ForeignKey(FileReference, related_name='people_with_avatar')

class House(models.Model):
    images = models.ManyToManyField(FileReference, related_name='houses_with_images')

class Document(model.Model):
    attachment = models.OneToOneField(FileReference, related_name='document_with_attachment')

因此,许多其他模型将使用引用FileReference模型的外键。

但有时,删除引用模型,并留下FileReference个对象。

我想删除没有外键引用的FileReference对象。

但是其他许多地方都有外键。

有没有找到所有参考资料的有效方法?即获取某个模型对象的引用计数?

1 个答案:

答案 0 :(得分:2)

我偶然发现了这个问题,我找到了一个解决方案。请注意,django==1.6不再受支持,因此此解决方案可能适用于django>=1.9

让我们说现在我们正在谈论其中的两个对象:

class FileReference(models.Model):
    pass

class Person(models.Model):
    avatar = models.ForeignKey(FileReference, related_name='people_with_avatar', on_delete=models.CASCADE)

正如您在ForeignKey.on_delete文档中所看到的,当您删除相关的FileReference对象时,也会删除引用的对象Person

现在提出你的问题。我们如何做到受人尊敬?我们希望Person删除FileReference对象也将被删除。

我们将使用post_delete signal

执行此操作
def delete_reverse(sender, **kwargs):
    try:
        if kwargs['instance'].avatar:
            kwargs['instance'].avatar.delete()
    except:
        pass

post_delete.connect(delete_reverse, sender=Person)

我们在那里做的是删除avatar删除Person字段中的引用。请注意,try: except:块是为了防止循环异常。

<强>附加

上述解决方案适用于所有未来的对象。如果要在没有引用的情况下删除所有过去的对象,请执行以下操作:

在您的包中添加以下文件和目录:management/commands/remove_unused_file_reference.py

from django.core.management.base import BaseCommand, CommandError


class Command(BaseCommand):

    def handle(self, *args, **options):

        file_references = FileReference.objects.all()
        file_reference_mapping = {file_reference.id: file_reference for file_reference in file_references}

        persons = Person.objects.all()
        person_avatar_mapping = {person.avatar.id: person for person in persons}


        for file_reference_id, file_reference in file_reference_mapping.items():
            if file_reference_id not in person_avatar_mapping:
                file_reference.delete()

完成后,请致电:python manage.py remove_unused_file_reference 这是基本想法,您可以将其更改为批量删除等...

我希望这对那里的人有所帮助。祝你好运!