Получить все связанные объекты модели Django
Как я могу получить список всех объектов модели, которые имеют ForeignKey, указывающие на объект? (Что-то вроде страницы подтверждения удаления в администраторе Django до DELETE CASCADE).
Я пытаюсь создать общий способ слияния дублирующих объектов в базе данных. В основном я хочу, чтобы все объекты, которые имеют ForeignKeys, указывают на объект "B", чтобы обновить его, чтобы указать на объект "A", поэтому я могу удалить "B", не потеряв ничего важного.
Спасибо за вашу помощь!
Ответы
Ответ 1
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://docs.djangoproject.com/en/1.10/ref/models/meta/#django.db.models.options.Options.get_fields (см. также обратное в источнике _get_fields()
)
Ответ 2
@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
это позволяет создать то, что отображает администратор django - связанные объекты, которые нужно удалить.
Ответ 3
Попробуйте.
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]
Ответ 4
for link in links:
objects = getattr(a, link).all()
Работает для связанных наборов, но не для ForeignKeys. Поскольку связанные с ними администраторы создаются динамически, просмотр имени класса проще, чем использование isinstance()
objOrMgr = getattr(a, link)
if objOrMgr.__class__.__name__ == 'RelatedManager':
objects = objOrMgr.all()
else:
objects = [ objOrMgr ]
for object in objects:
# Do Stuff
Ответ 5
Ниже приведен пример использования django для получения всех связанных объектов
from django.db.models.deletion import Collector
collector = Collector(using="default")
collector.collect([a])
print collector.data
Ответ 6
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()"
Ответ 7
links = [rel.get_accessor_name() для rel в a._meta.get_all_related_objects()]
Затем вы можете использовать что-то вроде этого, чтобы получить все связанные объекты:
для ссылки в ссылках: objects = getattr (a, link.name).all() для объекта в объектах: # сделать что-то со связанным экземпляром объекта
Из Django 1.10 offical docs:
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
Ответ 8
Вот еще один способ получить список полей (только имен) в связанных моделях.
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
Ответ 9
К сожалению, user._meta.get_fields() возвращает только отношения, доступные от пользователя, однако у вас может быть связанный объект, который использует related_name = '+'. В таком случае отношение не будет возвращено user._meta.get_fields(). Поэтому, если вам нужен общий и надежный способ слияния объектов, я бы предложил использовать упомянутый выше коллекционер.