python - Django:如何确定一个对象是否被任何其他对象引用?
问题描述
概括
在 Django 中,确定数据库中是否有引用给定对象的对象的最简单方法是什么?
细节
考虑 Django 的相关对象参考中的这个最小示例:
from django.db import models
class Reporter(models.Model):
pass
class Article(models.Model):
reporter = models.ForeignKey(Reporter, on_delete=models.CASCADE)
我们如何确定是否有任何对象(不仅仅是 对象)通过 a 、 a或 aArticle
指向给定对象?Reporter
OneToOneField
ForeignKey
ManyToManyField
换句话说,我们想确定给定对象是否有任何反向关系。
因为Article
这很简单,我们可以只得到 eg reporter.article_set.count()
,但以后可能会添加其他也指向 的模型Reporter
,这些也必须考虑在内。
示例用例
一个示例用例是我们希望在对象被任何其他对象引用时立即阻止修改。或者我们可以使用它来强制执行一种类似于on_delete=models.PROTECT
机制的行为。
解决方案
Model._meta
这是一个使用API的工作解决方案,但我不确定这是否是最好的方法。希望得到更好的答案。
基本上,给定一个对象,我们得到一个它的反向关系列表,然后,对于其中的每一个,我们检查关系中是否有任何对象。
# just any given reporter object
obj = Reporter.objects.first()
# assume no references to obj
obj_has_reverse = False
# skip for new objects (i.e. those not yet saved to database)
if obj.id is not None:
# reverse relation "fields" on the Reporter model are auto-created and
# not concrete
for reverse in [f for f in obj._meta.get_fields()
if f.auto_created and not f.concrete]:
# in case the related name has been customized
name = reverse.get_accessor_name()
# one-to-one requires a special approach
has_reverse_one_to_one = reverse.one_to_one and hasattr(obj, name)
has_reverse_other = not reverse.one_to_one and getattr(obj, name).count()
if has_reverse_one_to_one or has_reverse_other:
obj_has_reverse = True
请注意,ForeignKey
和ManyToManyField
返回一个相关管理器的反向关系,所以我们可以检查例如count()
. 但是,反向关系 forOneToOneField
不会返回 a RelatedManager
。DoesNotExist
如果没有相关对象,它会引发异常,如docs中所述。另请参阅的来源。reverse_related
推荐阅读
- amazon-s3 - 如何在 CloudFormation 模板中为 lambda .zip 代码指定 S3 存储桶区域
- excel - 带有两个输入变量的 VBA for 循环返回“无效的下一个控制变量引用”错误
- python - Pyspark 环境变量
- javascript - 如何将 showPanel:boolean 属性应用于 matautocomplete,如文档中所示
- swift - 为什么我的 UISlider 与我加载模拟器时给它的值不匹配
- google-drive-api - Colab 在谷歌驱动器中将项目文件夹设置为默认值
- html - 我如何像在组件站点上一样引导 4 菜单导航
- python - 使用带有条件的 numpy 更快地遍历像素的方法?
- django-models - 如何从 django 中的 DateField 中仅过滤日期(DD)
- php - 在第二个 foreach 循环中 strpos 无法正常工作