Как я могу получить список всех объектов модели, у которых ForeignKey указывает на объект? (Что-то вроде страницы подтверждения удаления в админке Django перед КАСКАДОМ УДАЛЕНИЯ).
Я пытаюсь найти общий способ объединения повторяющихся объектов в базе данных. По сути, я хочу, чтобы все объекты, у которых ForeignKeys указывает на объект «B», были обновлены, чтобы они указывали на объект «A», чтобы затем я мог удалить «B», не теряя ничего важного.
Спасибо за вашу помощь!
python
django
django-models
merge
erikcw
источник
источник
set
связанный объект указывал на букву А?Ответы:
Джанго <= 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()
источника)источник
all()
Часть потерпит неудачу наOneToOneField
. Вы должны как-то это обнаружить._meta.get_fields()
: docs.djangoproject.com/en/1.10/ref/models/meta/… (см. Такжеreverse
в_get_fields()
источнике)_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
)@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:
[ 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. Поскольку связанные менеджеры создаются динамически, смотреть на имя класса проще, чем выполнять 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())
Примечание. RemovedInDjango110Предупреждение: get_all_related_objects - это неофициальный API, который устарел. Вы можете заменить его на 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
источник
К сожалению, user._meta.get_fields () возвращает только отношения, доступные пользователю, однако у вас может быть какой-то связанный объект, который использует related_name = '+'. В таком случае отношение не будет возвращено user._meta.get_fields (). Поэтому, если вам нужен универсальный и надежный способ слияния объектов, я бы предложил использовать упомянутый выше Collector.
источник