Джанго: Как определить, на какой объект ссылается какой-либо другой объект? - PullRequest
0 голосов
/ 15 февраля 2019

summary

В Django, какой самый простой способ определить, есть ли какие-либо объекты в нашей базе данных, которые ссылаются на данный объект?

details

Учтите этоминимальный пример из справочника связанных объектов :

from django.db import models

class Reporter(models.Model):
    pass

class Article(models.Model):
    reporter = models.ForeignKey(Reporter, on_delete=models.CASCADE)

Как мы можем определить, есть ли какие-либо объекты, поэтому не только Article объекты, которые указывают на данный Reporter объект, через OneToOneField, ForeignKey или ManyToManyField?

Другими словами, мы хотим определить, существуют ли какие-либо обратные отношения к данному объекту.

Для Article это просто, мы можем просто получить, например,reporter.article_set.count(), но позже могут быть добавлены другие модели, которые также указывают на Reporter, и это также необходимо учитывать.

пример варианта использования

пример варианта использованияЗдесь мы хотим предотвратить изменение, как только на объект ссылается любой другой объект.Или мы могли бы использовать его для обеспечения поведения, подобного механизму on_delete=models.PROTECT.

1 Ответ

0 голосов
/ 15 февраля 2019

Вот рабочее решение, использующее Model._meta API , но я не уверен, что это лучший способ сделать это.Надеясь на лучшие ответы.

По сути, для данного объекта мы получаем список его обратных отношений, а затем для каждого из них мы проверяем, есть ли какие-либо объекты в этом отношении.

# just any given reporter object
obj = Reporter.objects.first()
# assume no references to obj
obj_has_reverse = False
# skip for new objects (i.e. those not yet saved to database)
if obj.id is not None:  
    # reverse relation "fields" on the Reporter model are auto-created and
    # not concrete
    for reverse in [f for f in obj._meta.get_fields() 
                    if f.auto_created and not f.concrete]:
        # in case the related name has been customized
        name = reverse.get_accessor_name()
        # one-to-one requires a special approach
        has_reverse_one_to_one = reverse.one_to_one and hasattr(obj, name)
        has_reverse_other = not reverse.one_to_one and getattr(obj, name).count()
        if has_reverse_one_to_one or has_reverse_other:
            obj_has_reverse = True

Обратите внимание, что обратное отношение для ForeignKey и ManyToManyField возвращает RelatedManager , поэтому мы можем проверить, например, count().Однако обратное отношение для OneToOneField не возвращает RelatedManager.Вызывает исключение DoesNotExist, если нет связанных объектов, как описано в документах .Также см. источник для reverse_related.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...