Django:如何查找引用模型的模型

12

我想警告或阻止用户删除其他实例引用的对象实例。有没有好的方法可以实现这一点?

其中一种方式是获取包含引用的模型列表,然后在它们上面尝试反向查找。有没有一种方法可以获取那个模型列表?或者有更好的方法吗?

在调查收集器建议时,我发现了一些相关信息,并编写了以下代码,可以找到将引用作为外键的类:

def find_related(cl, app):
    """Find all classes which are related to the class cl (in app) by 
    having it as a foreign key."""

    from django.db import models

    all_models = models.get_models()
    ci_model = models.get_model(app, cl)
    for a_model in all_models:
        for f in a_model._meta.fields:
            if isinstance(f, ForeignKey) and (f.rel.to == ci_model):
                print a_model.__name__

根据在 collect 中使用该代码的建议:

def find_related(instance):
"""Find all objects which are related to instance."""

for related in instance._meta.get_all_related_objects():
    acc_name = related.get_accessor_name()
    referers = getattr(instance, acc_name).all()
    if referers:
        print related

感谢您更新这个问题并提供最终解决方案。做得非常好。 - Spike
你有一个函数 find_related,它接受 (cl, app) 作为参数,而 get_model 接受 (app, cl)。这真的很令人困惑!此外,如果其他人正在阅读这篇文章,请注意 clapp 是字符串 - 不要传递对象! - Casebash
1个回答

4

Django有一个称为Collector类的东西。在执行模型删除时,Django使用它。它所做的事情似乎正是你想要的。通过调用collect(),它会在模型图中找到对该对象的所有引用。此外,它提供了一种删除所有找到的对象的方法,即调用delete()

尽管如此,我从未自己使用过这个类,我只知道它的存在。API有些复杂,但如果你愿意深入挖掘Django的内部,它可能会节省你很多编码时间。


这看起来很有前途,但我正在使用1.0版本,它只有Collector的前身 - CollectedObjects,它似乎没有类似的方法。在(https://dev59.com/1XRC5IYBdhLWcg3wAcXU)中使用CollectedObjects查找由要删除的实例引用的对象。 - Mitch
我们能否假设 (a) 你不能升级到更高版本有充分的理由,(b) 同样地,你不能仅使用收集器? - Marcin
@Mitch:是的,我同意Marcin的观点,如果你不能升级,你可以尝试使用Collector.collect()实现作为你自己代码的基础。总体而言,Django代码并不干净,但经过一些分析后,它仍然可以使用。 - julx
谢谢。我查看了collect,只需要使用一小部分就能完成我想要的事情。另一个参考是:https://dev59.com/j3E95IYBdhLWcg3wm_Mu - Mitch

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接