Конкатенировать определенное поле из дочерних объектов в родительский объект?

У меня есть две модели:

class Chapter(models.Model):
    chapter = models.IntegerField()
    verses_amount = models.IntegerField()
    chapter_content = models.TextField()
    

class Verse(models.Model):
    chapter = models.ForeignKey(Chapter, on_delete=CASCADE)
    verse = models.TextField()
    verse_number = models.IntegerField()

В поле Verse я сохраняю абзац в поле verse. Как я могу запросить всех детей (Verse), получить их verse параграф, конкатенировать их и поместить в Chapter.chapter_content?

Eg

verses = Verse.objects.filter()[0:2]
for verse in verses:
    print(verse.verse)

>> 'Lorem Ipsum.'
>> 'Second Lorem Ipsum Iteration 2.'

В родительском Chapter я хочу, чтобы chapter_content хранил два значения как одну длинную строку:

"Lorem Ipsum. Вторая итерация Lorem Ipsum 2.'

Вы можете сделать что-то вроде этого:

chapter = Chapter.objects.get(chapter=1)  # or whatever chapter you want to get

content = ""

for verse in chapter.verse_set.all():
   content += f"{verse.verse} "

content = content.rstrip()

chapter.chapter_content = content
chapter.save()

Но это плохая практика хранить стих как в Verse объектах, так и в Chapter объектах, потому что что если вы хотите обновить только один стих?

Вы можете попробовать сделать chapter_content свойством метода в Chapter модели.

class Chapter(models.Model):
    chapter = models.IntegerField()
    verses_amount = models.IntegerField()

    @property
    def chapter_content(self):
        content = ""
        for verse in self.verse_set.all():
            content += f"{verse.verse} "
        return content.rstrip()
    

class Verse(models.Model):
    chapter = models.ForeignKey(Chapter, on_delete=CASCADE)
    verse = models.TextField()
    verse_number = models.IntegerField()

Обратите внимание, что вам все равно придется сортировать стихи по их порядковому номеру.

Вернуться на верх