获取所有相关的Django模型对象

eri*_*kcw 84 python django merge django-models

如何获取具有指向对象的ForeignKey的所有模型对象的列表?(类似于DELETE CASCADE之前Django管理员中的删除确认页面).

我试图想出一种在数据库中合并重复对象的通用方法.基本上我希望所有具有ForeignKeys指向对象"B"的对象被更新为指向对象"A",这样我就可以删除"B"而不会丢失任何重要的东西.

谢谢你的帮助!

rob*_*les 81

Django <= 1.7

这为您提供了所有相关对象的属性名称:

links = [rel.get_accessor_name() for rel in a._meta.get_all_related_objects()]
Run Code Online (Sandbox Code Playgroud)

然后,您可以使用类似的东西来获取所有相关对象:

for link in links:
    objects = getattr(a, link).all()
    for object in objects:
        # do something with related object instance
Run Code Online (Sandbox Code Playgroud)

我花了一些时间试图解决这个问题,所以我可以在我的一个模型上实现一种"观察者模式".希望它有用.

Django 1.8+

使用_meta.get_fields():https://docs.djangoproject.com/en/1.10/ref/models/meta/#django.db.models.options.Options.get_fields(在_get_fields()源代码中也见反向)

  • `all()`部分将在`OneToOneField`上失败.你必须以某种方式检测它. (7认同)
  • 关于`_meta.get_fields()`提示,这是我的解决方案的一部分:`links = [field.get_accessor_name()用于obj._meta.get_fields()中的字段,如果是issubclass(type(field),ForeignObjectRel) ]`(给出来自django.db.models.fields.related import ForeignObjectRel`) (3认同)
  • 它不显示ManyToMany连接并且已弃用.在Django 1.8+中,建议将其替换为`_meta.get_fields()`:https://docs.djangoproject.com/en/1.10/ref/models/meta/#django.db.models.options.Options.get_fields (参见`_get_fields()`源中的`reverse`) (2认同)

IMF*_*her 18

@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
Run Code Online (Sandbox Code Playgroud)

这允许您创建django管理员显示的内容 - 要删除的相关对象.


buc*_*ley 7

试一试.

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]
Run Code Online (Sandbox Code Playgroud)


Boj*_*vic 6

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
Run Code Online (Sandbox Code Playgroud)

来自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
]
Run Code Online (Sandbox Code Playgroud)

因此,通过采用已批准的示例,我们将使用:

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
Run Code Online (Sandbox Code Playgroud)


小智 5

for link in links:
    objects = getattr(a, link).all()
Run Code Online (Sandbox Code Playgroud)

适用于相关集,但不适用于ForeignKeys.由于相关管理器是动态创建的,因此查看类名比执行isinstance()更容易

objOrMgr = getattr(a, link)
 if objOrMgr.__class__.__name__ ==  'RelatedManager':
      objects = objOrMgr.all()
 else:
      objects = [ objOrMgr ]
 for object in objects:
      # Do Stuff
Run Code Online (Sandbox Code Playgroud)


dig*_*PBK 5

以下是django用于获取所有相关对象的内容

from django.db.models.deletion import Collector
collector = Collector(using="default")
collector.collect([a])

print collector.data
Run Code Online (Sandbox Code Playgroud)


Sli*_*eam 5

Django 1.9
get_all_related_objects() 已被弃用

#Example: 
user = User.objects.get(id=1)
print(user._meta.get_fields())
Run Code Online (Sandbox Code Playgroud)

注意: RemovedInDjango110Warning: 'get_all_related_objects 是一个已被弃用的非官方 API。您可以将其替换为“get_fields()”