Я видел, как газовщик уже дал ответ на ваш вопрос, но я все еще собираюсь написать ответ по двум причинам:
Я думаю, вам нужны еще несколько указателей, чтобы почему предложение gasmans является лучшим решением, чем ваше, но это очень много, чтобы написать в комментарии.
Я реализовывал подобное решение раньше, где тамявляется объектом верхнего уровня, похожим на Article, с несколькими переупорядочиваемыми дочерними объектами, в которых находится фактическое содержимое.
Почему вы должны сделать Article
подклассом страницы
Вы решили не делать Article
подклассом Page
, и вы сказали, что это потому, что сам Article
не содержит никакого контента, только метаданные о статье. Это не очень странный мыслительный процесс, но я думаю, что вы смотрите на неправильные требования для вашей Article
модели.
Давайте посмотрим на собственную модель Page
трясогузки. Какие функции он предоставляет «из коробки»?
- Он предоставляет древовидную структуру с родительскими и дочерними страницами, так что ваша страница может быть размещена где-то в иерархии вашего сайта
- Предоставляет
slug_field
, так что Wagtail может автоматически обрабатывать ссылки на вашу страницу. - Предоставляет функции для черчения, публикации и отмены публикации.
Wagtail не диктуетчто-нибудь о контенте, оставляя вам решать, какой контент вы хотите поместить в свой подкласс Page
, если таковой имеется. Примеры страниц, у которых нет тела:
- Контактные формы.
- Страницы указателей блогов.
Хорошие вопросы, которые вы можете задать при принятии решенияхотите ли вы, чтобы Model
был подклассом Page
:
- Хочу ли я, чтобы у этого объекта был свой собственный URL?
- Хочу ли я иметь возможностьразместить этот объект где-то внутри иерархии моего сайта?
- Хочу ли я иметь преимущества SEO для этого объекта?
- Хочу ли я иметь возможность публиковать / отменять публикацию этого объекта или нет?
В вашем случае Article
вы могли бы ответить «да» почти на все эти вопросы, поэтому было бы разумно сделать его подклассом Page
. Таким образом, вам не нужно заново изобретать колесо.
Как вы определяете фактическое «тело» вашей страницы, зависит от вас. Вы можете поместить фактический контент либо в фрагменты, либо в подстраницы к этой статье. Или вы можете даже создать список StreamFields внутри вашей модели.
Как реализовать упорядоченный субконтент.
Ранее я реализовал такую структуру. То, как я это сделал, было очень похоже на то, что предлагает газовик.
В моем случае мне нужно было создать веб-сайт, на котором можно было бы найти объект (например, статью) и отобразить различные типы модулей объяснения для него. Для каждого документа я создал ArticlePage
, а для каждого модуля объяснения я создал фрагмент с именем ExplanationModule
.
Затем я создал сквозную модель с упорядочением и добавил RoutablePageMixin в класс, напримерГасман объясняет.
Структура выглядит примерно так:
@register_snippet
class ArticlePageModule(models.Model):
...
title = models.CharField(max_length=100)
body = StreamField(LAYOUT_STREAMBLOCKS, null=True, blank=True)
panels = [
FieldPanel('title'),
StreamFieldPanel('body'),
]
class ArticlePageModulePlacement(Orderable, models.Model):
page = ParentalKey('articles.ArticlePage', on_delete=models.CASCADE, related_name='article_module_placements')
article_module = models.ForeignKey(ArticlePageModule, on_delete=models.CASCADE, related_name='+')
slug = models.SlugField()
panels = [
FieldPanel('slug'),
SnippetChooserPanel('article_module'),
]
class ArticlePage(Page, RoutablePageMixin):
# Metadata and other member values
....
content_panels = [
...
InlinePanel('article_module_placements', label="Modules"),
]
@route(r'^module/(?P<slug>[\w\-]+)/$')
def page_with_module(self, request, slug=None):
self.article_module_slug = slug
return self.serve(request)
def get_context(self, request):
context = super().get_context(request)
if hasattr(self, 'article_module_slug'):
context['ArticlePageModule'] = self.article_module_placements.filter(slug = self.article_module).first().article_module
return context
Это выглядит следующим образом:
Создайте фрагмент ArticlePageModule, которыйэто просто некоторый контент, такой как заголовок и тело.
Создайте ArticlePageModulePlacement, который связывает ArticlePage с модулем, и добавляет следующее:
- Slug
- Порядок (поскольку он подразделяет подстраиваемое микширование)
Создайте ArticlePage, которая выполняет две вещи:
- Определите панель ArticlePageModuleplacement, которая позволяет добавлять ArticlePageModulePlacements
- Подкласс RoutablePagemixin, как описано в ответе gasman.
Это дает вам Wagнадежный, многоразовый и надежный способ создания статей с помощью SubContent. Модули не отображаются на вкладках, но будут отображаться на странице макета страницы под панелью «Модули».