Разрешение поля 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)