I have some problems saving an Article page in wagtail, I have 3 classes: ArticlePageModule, ArticlePageModulePlacement and ArticlePage
The error says:
File "/opt/miniconda3/envs/nefodev/lib/python3.7/site-packages/django/db/models/base.py", line 1222, in full_clean
raise ValidationError(errors)
django.core.exceptions.ValidationError: {'title': ['This field cannot be blank.']}
My intention is to have a section of dynamic articles that you can add using the snippet like this:
- Page with several articles (preview only).
- By clicking on the article send to your own article page
- In the wagtail admin you can manage the articles by publication dates
My code (supported by this code: this)
from django.db import models
from wagtail.core.fields import StreamField
from wagtail.admin.edit_handlers import FieldPanel, StreamFieldPanel, InlinePanel
from wagtail.images.edit_handlers import ImageChooserPanel
from wagtail.core.models import Page, Orderable
from modelcluster.fields import ParentalKey
from wagtail.snippets.models import register_snippet
from wagtail.snippets.edit_handlers import SnippetChooserPanel
from wagtail.images.blocks import ImageChooserBlock
from wagtail.core import blocks
from wagtail.contrib.routable_page.models import RoutablePageMixin, route
# Create your models here.
@register_snippet
class ArticlePageModule(models.Model):
title = models.CharField(max_length=80)
subtitle = models.CharField(max_length=50)
thumbImage = models.ForeignKey(
'wagtailimages.Image',
null=True,
blank=True,
on_delete=models.SET_NULL,
related_name='+'
)
panels = [
FieldPanel('title'),
FieldPanel('subtitle'),
ImageChooserPanel('thumbImage')
]
def __str__(self):
return self.title
class ArticlePageModulePlacement(Orderable, models.Model):
page = ParentalKey('blog.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):
content = StreamField([
('heading', blocks.CharBlock()),
('content', blocks.RichTextBlock()),
('image', ImageChooserBlock()),
])
content_panels = [
InlinePanel('article_module_placements', label="Modules"),
StreamFieldPanel('content')
]
@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