获取所有相关的Django模型对象
我怎样才能得到一个所有的模型对象有一个ForeignKey指向一个对象的列表? (类似DELETE CASCADE之前的Djangopipe理员中的删除确认页面)。
我试图想出一个在数据库中合并重复对象的通用方法。 基本上我希望所有具有ForeignKeys指向对象“B”的对象都被更新为指向对象“A”,这样我就可以删除“B”而不会丢失任何重要的东西。
谢谢你的帮助!
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
我花了一段时间试图弄清楚这一点,所以我可以在我的一个模型上实现一种“观察者模式”。 希望这是有帮助的。
Django 1.8+
使用_meta.get_fields()
: https : _meta.get_fields()
请参阅_get_fields()
源中的反向)
@ digitalPBK是接近…这可能是你正在寻找使用Django内置的东西
from django.db.models.deletion import Collector from django.contrib.admin.util import NestedObjects collector = NestedObjects(using="default") #database name collector.collect([objective]) #list of objects. single one won't do print collector.data
这允许您创builddjango admin显示的内容 – 要删除的相关对象。
试试这个。
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]
for link in links: objects = getattr(a, link).all()
适用于相关套件,但不适用于ForeignKeys。 由于RelatedManagers是dynamic创build的,因此查看类名比执行isinstance()更容易
objOrMgr = getattr(a, link) if objOrMgr.__class__.__name__ == 'RelatedManager': objects = objOrMgr.all() else: objects = [ objOrMgr ] for object in objects: # Do Stuff
以下是django用来获取所有相关对象的内容
from django.db.models.deletion import Collector collector = Collector(using="default") collector.collect([a]) print collector.data
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()'replace它
links = [rel.get_accessor_name()for rel in a._meta.get_all_related_objects()]然后,您可以使用这样的东西来获取所有相关的对象:
链接的链接:objects = getattr(a,link.name).all()对象中的对象:#做一些相关的对象实例
从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
这是另一种获取相关模型中的字段列表(仅限名称)的方法。
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
不幸的是,user._meta.get_fields()只返回用户可访问的关系,但是,你可能有一些相关的对象,它使用related_name ='+'。 在这种情况下,关系不会被user._meta.get_fields()返回。 因此,如果你需要通用和健壮的方式来合并对象,我build议使用上面提到的收集器。