Разрешение поля ForeignKey, указывающего на модель, к которой оно принадлежит

У меня есть класс модели в Django, который имеет ForeignKey, ссылающийся на модель, к которой он фактически принадлежит:

class Foo(models.Model):
    name = models.CharField(max_length=256, verbose_name="Name")
    #... some other fields
    bar = models.ForeignKey(
        "self", on_delete=models.CASCADE, null=True, blank=True
    )
    def __str__(self):
        return self.name

Я хочу добавить в этот класс пользовательский метод, который на лету разрешает name в новом поле, например bar_resolved при инстанцировании его в QuerySet в представлении:

from .models import Foo

foo = Foo.objects.all()
# do stuff

Я пробовал следующее:

class Foo(models.Model):
    name = models.CharField(max_length=256, verbose_name="Name")
    #... some other fields
    bar = models.ForeignKey(
        "self", on_delete=models.CASCADE, null=True, blank=True
    )
    # preparing the resolved bar field which should contain the 'name' value corresponding to the id:
    bar_resolved = models.CharField(
        max_length=256,
        verbose_name="Bar name resolved",
        null=True
    )

    def __str__(self):
        return self.name

    def resolve(self):
        if self.bar:
            self.bar_resolved = self.bar.name
        return super(Foo, self).resolve()

Тогда, на мой взгляд:

from .models import Foo

foo = Foo.objects.all()
foo.resolve()

но повышает: 'QuerySet' object has no attribute 'resolve'

Как я могу этого добиться? И нужно ли мне для этого жестко кодировать поле 'resolved' в моей модели (я думаю, что это излишне)?

Я не понимаю, зачем вам иметь Foreing key, ссылающийся на себя в базе данных.

Вместо использования resolve, вы, вероятно, могли бы сделать это при сохранении задолго до этого - то есть при установке значения "bar"

Другая идея, которая приходит на ум - установить его в __ init__ метода модели ссылка на Stack

надеюсь, это поможет.

def save(self, force_insert: bool = False, force_update: bool = False) -> None:
    if self.field is None:
        self.field = "value"
    # and so on...
    return super().save(force_insert, force_update)

Один из способов - annotate...[Django-doc] ваш queryset, используя F expressions...[Django-doc] с полем имени bar:

from django.db.models import F

foos = Foo.objects.annotate(bar_resolved=F("bar__name")).all()
for foo in foos:
    print(foo.bar_resolved)
Вернуться на верх