如何获取具有指向对象的 ForeignKey 的所有模型对象的列表? (类似于 DELETE CASCADE 之前 Django 管理员中的删除确认页面)。
我正在尝试提出一种合并数据库中重复对象的通用方法。基本上,我希望将所有具有 ForeignKeys 指向对象“B”的对象更新为指向对象“A”,这样我就可以删除“B”而不会丢失任何重要的东西。
谢谢你的帮助!
set
相关对象如何指向 A ?
Django <= 1.7
这为您提供了所有相关对象的属性名称:
links = [rel.get_accessor_name() for rel in a._meta.get_all_related_objects()]
然后,您可以使用类似这样的方法来获取所有相关对象:
for link in links:
objects = getattr(a, link).all()
for object in objects:
# do something with related object instance
我花了一段时间试图弄清楚这一点,这样我就可以在我的一个模型上实现一种“观察者模式”。希望它有帮助。
姜戈 1.8+
使用 _meta.get_fields()
:https://docs.djangoproject.com/en/1.10/ref/models/meta/#django.db.models.options.Options.get_fields(另请参阅 _get_fields()
源中的反向)
@digitalPBK 很接近...这可能是您正在寻找的使用 Django 的内置内容,该内容在 Django 管理员中用于在删除期间显示相关对象
from django.contrib.admin.utils import NestedObjects
collector = NestedObjects(using="default") #database name
collector.collect([objective]) #list of objects. single one won't do
print(collector.data)
这允许您创建 Django 管理员显示的内容 - 要删除的相关对象。
Collector
(在第 1 行导入)?
试试这个。
class A(models.Model):
def get_foreign_fields(self):
return [getattr(self, f.name) for f in self._meta.fields if type(f) == models.fields.related.ForeignKey]
下面是django用来获取所有相关对象的
from django.db.models.deletion import Collector
collector = Collector(using="default")
collector.collect([a])
print collector.data
links = [rel.get_accessor_name() for rel in a._meta.get_all_related_objects()]
然后,您可以使用类似这样的方法来获取所有相关对象:
for link in links:
objects = getattr(a, link.name).all()
for object in objects:
# do something with related object instance
来自 Django 1.10 官方文档:
MyModel._meta.get_all_related_objects() 变为:
[
f for f in MyModel._meta.get_fields()
if (f.one_to_many or f.one_to_one)
and f.auto_created and not f.concrete
]
因此,通过采用批准的示例,我们将使用:
links = [
f for f in MyModel._meta.get_fields()
if (f.one_to_many or f.one_to_one)
and f.auto_created and not f.concrete
]
for link in links:
objects = getattr(a, link.name).all()
for object in objects:
# do something with related object instance
python for link in links: objects = getattr(a, link.name).all() for object in objects:
for link in links:
objects = getattr(a, link).all()
适用于相关集,但不适用于 ForeignKeys。由于 RelatedManagers 是动态创建的,因此查看类名比使用 isinstance() 更容易
objOrMgr = getattr(a, link)
if objOrMgr.__class__.__name__ == 'RelatedManager':
objects = objOrMgr.all()
else:
objects = [ objOrMgr ]
for object in objects:
# Do Stuff
Django 1.9 get_all_related_objects() 已被弃用
#Example:
user = User.objects.get(id=1)
print(user._meta.get_fields())
注意: RemovedInDjango110Warning: 'get_all_related_objects 是一个已被弃用的非官方 API。您可以将其替换为“get_fields()”
不幸的是,user._meta.get_fields() 只返回用户可访问的关系,但是,您可能有一些相关对象,它使用related_name='+'。在这种情况下,user._meta.get_fields() 不会返回关系。因此,如果您需要通用且强大的方法来合并对象,我建议使用上面提到的收集器。
这是获取相关模型中的字段列表(仅限名称)的另一种方法。
def get_related_model_fields(model):
fields=[]
related_models = model._meta.get_all_related_objects()
for r in related_models:
fields.extend(r.opts.get_all_field_names())
return fields
不定期副业成功案例分享
all()
部分将在OneToOneField
上失败。你必须以某种方式检测它。_meta.get_fields()
:docs.djangoproject.com/en/1.10/ref/models/meta/…(另请参阅_get_fields()
源中的reverse
)_meta.get_fields()
提示,这是我的解决方案的一部分:links = [field.get_accessor_name() for field in obj._meta.get_fields() if issubclass(type(field), ForeignObjectRel)]
(给定from django.db.models.fields.related import ForeignObjectRel
)