Страницы в стиле блога в Django с различными типами контента. Лучшая структура модели

Я относительно новичок в разработке Django. Я создаю сайт, где есть раздел с учебниками. Допустим, для моего вопроса нужен учебник по Linked List. Поскольку все учебники будут в основном одинаковыми, похоже, что шаблоны будут хорошо работать здесь. Я хочу добиться того, чтобы я мог создавать новые страницы (записи учебников) в панели администратора, с текстовыми полями и так далее (что-то вроде блога, только без актуальности дат, а не содержания учебников). Сложность для меня заключается в том, что в одной обучающей записи может быть разное количество данных разных типов. Например, одна из них может иметь структуру:

  • текст
  • код
  • текст
  • изображение
  • текст
  • код

и еще один:

  • текст
  • изображение
  • код

А если я делаю новую запись, она должна генерироваться с помощью шаблона, как это обычно делается в Django. Я думал о трех способах удовлетворить это динамическое поведение, но я вижу трудности в каждом из них и хотел бы знать, какая практика будет лучшей.

Итак, структура будет похожа на Блог:

class TutorialPost(models.Model):
    title = models.CharField(max_length=200, unique=True)
    text_content = models.TextField()
    code_block = models.TextField()
    #....

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

Я также думал о том, чтобы иметь только одно текстовое поле и обрабатывать его как поле markdown. Таким образом, я бы взял пакет markdown, такой как Django MarkdownX, и скомпилировал бы контент text_content. Проблема здесь в том, что у меня гораздо меньше свободы в том, как может выглядеть дизайн, например, блока кода (подсветка синтаксиса, фон и так далее).

Моя последняя идея заключалась в том, чтобы снова иметь только одно поле text_content как вариант ввода, но поместить обычный текст, код, изображения и т.д. в собственные теги (похожие на три акцента, используемые здесь, на stackoverflow) и обработать/парсить их после этого, чтобы представить их в правильном порядке по запросу.

Я с нетерпением жду ответа.

Думаю, вы можете сделать модель для каждого типа контента, например, так.

class TextContent(models.Model):
    body = models.TextField()
    post = models.ForeignKey(TutorialPost, on_delete=models.CASCADE)

Таким образом, вы можете создать несколько "блоков контента" одного времени в одном посте.

Для заказа можно создать пользовательский OrderField, вот пример.

from django.core.exceptions import ObjectDoesNotExist

class OrderField(models.PositiveIntegerField):
    def __init__(self, for_fields=None, *args, **kwargs):
        self.for_fields = for_fields
        super().__init__(*args, **kwargs)

    def pre_save(self, model_instance, add):
        if getattr(model_instance, self.attname) is None:
            # No current value
            try:
                qs = self.model.objects.all()
                if self.for_fields:
                    # Filter by objects with the same field values
                    # for the fields in 'for_fields'
                    query = {field: getattr(model_instance, field)\
                        for field in self.for_fields}
                    qs = qs.filter(**query)
                # Get the order of the last item
                last_item = qs.latest(self.attname)
                value = last_item.order + 1
            except ObjectDoesNotExist:
                value = 0
            setattr(model_instance, self.attname, value)
            return value
        else:
            return super().pre_save(model_instance, add)
Вернуться на верх