Home page can now host richt content
This commit is contained in:
parent
9b4bb6c9f1
commit
38733808ed
7 changed files with 191 additions and 5 deletions
|
@ -1,4 +1,4 @@
|
||||||
from wagtail.blocks import RichTextBlock
|
from wagtail.blocks import RichTextBlock, BlockQuoteBlock
|
||||||
from wagtail.embeds.blocks import EmbedBlock
|
from wagtail.embeds.blocks import EmbedBlock
|
||||||
|
|
||||||
from base.blocks import StreamBlock, HeadingBlock, ImageBlock
|
from base.blocks import StreamBlock, HeadingBlock, ImageBlock
|
||||||
|
@ -6,6 +6,7 @@ from wagtailcodeblock.blocks import CodeBlock
|
||||||
|
|
||||||
class BlogPostBlock(StreamBlock):
|
class BlogPostBlock(StreamBlock):
|
||||||
heading_block = HeadingBlock()
|
heading_block = HeadingBlock()
|
||||||
|
blockquote = BlockQuoteBlock()
|
||||||
paragraph = RichTextBlock(blank=True)
|
paragraph = RichTextBlock(blank=True)
|
||||||
code = CodeBlock(label='Code snippet')
|
code = CodeBlock(label='Code snippet')
|
||||||
image_block = ImageBlock()
|
image_block = ImageBlock()
|
||||||
|
|
22
blog/migrations/0014_alter_blogpage_body.py
Normal file
22
blog/migrations/0014_alter_blogpage_body.py
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
# Generated by Django 5.0.2 on 2024-04-05 16:56
|
||||||
|
|
||||||
|
import wagtail.blocks
|
||||||
|
import wagtail.embeds.blocks
|
||||||
|
import wagtail.fields
|
||||||
|
import wagtail.images.blocks
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('blog', '0013_alter_blogpage_body'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='blogpage',
|
||||||
|
name='body',
|
||||||
|
field=wagtail.fields.StreamField([('heading_block', wagtail.blocks.StructBlock([('heading_text', wagtail.blocks.CharBlock(form_classname='title', required=True)), ('size', wagtail.blocks.ChoiceBlock(blank=True, choices=[('', 'Select a heading size'), ('h2', 'H2'), ('h3', 'H3'), ('h4', 'H4')], required=False))])), ('blockquote', wagtail.blocks.BlockQuoteBlock()), ('paragraph', wagtail.blocks.RichTextBlock(blank=True)), ('code', wagtail.blocks.StructBlock([('language', wagtail.blocks.ChoiceBlock(choices=[('bash', 'Bash/Shell'), ('css', 'CSS'), ('dart', 'Dart'), ('docker', 'Docker'), ('elixir', 'Elixir'), ('go', 'Go'), ('html', 'HTML'), ('javascript', 'Javascript'), ('json', 'JSON'), ('kotlin', 'Kotlin'), ('python', 'Python'), ('rust', 'Rust'), ('swift', 'Swift'), ('toml', 'TOML'), ('yaml', 'YAML')], help_text='Coding language', identifier='language', label='Language')), ('code', wagtail.blocks.TextBlock(identifier='code', label='Code'))], label='Code snippet')), ('image_block', wagtail.blocks.StructBlock([('image', wagtail.images.blocks.ImageChooserBlock(required=True)), ('caption', wagtail.blocks.CharBlock(required=False)), ('attribution', wagtail.blocks.CharBlock(required=False))])), ('embed_block', wagtail.embeds.blocks.EmbedBlock(help_text='Insert a URL to embed. For example, https://www.youtube.com/watch?v=SGJFWirQ3ks', icon='media'))], blank=True, help_text='Write anything'),
|
||||||
|
),
|
||||||
|
]
|
|
@ -14,6 +14,7 @@ from wagtail.snippets.models import register_snippet
|
||||||
from blog.blocks import BlogPostBlock
|
from blog.blocks import BlogPostBlock
|
||||||
from wagtailseo.models import SeoMixin, SeoType
|
from wagtailseo.models import SeoMixin, SeoType
|
||||||
|
|
||||||
|
|
||||||
class BlogIndexPage(SeoMixin, Page):
|
class BlogIndexPage(SeoMixin, Page):
|
||||||
intro = RichTextField(blank=True)
|
intro = RichTextField(blank=True)
|
||||||
|
|
||||||
|
@ -29,6 +30,7 @@ class BlogIndexPage(SeoMixin, Page):
|
||||||
]
|
]
|
||||||
promote_panels = SeoMixin.seo_panels
|
promote_panels = SeoMixin.seo_panels
|
||||||
|
|
||||||
|
|
||||||
class BlogTagIndexPage(Page):
|
class BlogTagIndexPage(Page):
|
||||||
|
|
||||||
def get_context(self, request):
|
def get_context(self, request):
|
||||||
|
@ -40,6 +42,7 @@ class BlogTagIndexPage(Page):
|
||||||
context['blogpages'] = blogpages
|
context['blogpages'] = blogpages
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
class BlogPageTag(TaggedItemBase):
|
class BlogPageTag(TaggedItemBase):
|
||||||
content_object = ParentalKey(
|
content_object = ParentalKey(
|
||||||
'BlogPage',
|
'BlogPage',
|
||||||
|
@ -47,6 +50,7 @@ class BlogPageTag(TaggedItemBase):
|
||||||
on_delete=models.CASCADE
|
on_delete=models.CASCADE
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class BlogPage(SeoMixin, Page):
|
class BlogPage(SeoMixin, Page):
|
||||||
date = models.DateField("Post date")
|
date = models.DateField("Post date")
|
||||||
intro = models.TextField()
|
intro = models.TextField()
|
||||||
|
@ -104,6 +108,7 @@ class BlogPageGalleryImage(Orderable):
|
||||||
FieldPanel('caption'),
|
FieldPanel('caption'),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@register_snippet
|
@register_snippet
|
||||||
class Author(models.Model):
|
class Author(models.Model):
|
||||||
name = models.CharField(max_length=255)
|
name = models.CharField(max_length=255)
|
||||||
|
@ -121,4 +126,4 @@ class Author(models.Model):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name_plural = 'Authors'
|
verbose_name_plural = 'Authors'
|
||||||
|
|
16
home/blocks.py
Normal file
16
home/blocks.py
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
from wagtail.blocks import RichTextBlock, BlockQuoteBlock
|
||||||
|
from wagtail.embeds.blocks import EmbedBlock
|
||||||
|
|
||||||
|
from base.blocks import StreamBlock, HeadingBlock, ImageBlock
|
||||||
|
from wagtailcodeblock.blocks import CodeBlock
|
||||||
|
|
||||||
|
class HomeContentBlock(StreamBlock):
|
||||||
|
heading_block = HeadingBlock()
|
||||||
|
paragraph = RichTextBlock(blank=True)
|
||||||
|
code = CodeBlock(label='Code snippet')
|
||||||
|
blockquote = BlockQuoteBlock()
|
||||||
|
image_block = ImageBlock()
|
||||||
|
embed_block = EmbedBlock(
|
||||||
|
help_text="Insert a URL to embed. For example, https://www.youtube.com/watch?v=SGJFWirQ3ks",
|
||||||
|
icon="media",
|
||||||
|
)
|
136
home/migrations/0006_alter_homepage_body.py
Normal file
136
home/migrations/0006_alter_homepage_body.py
Normal file
|
@ -0,0 +1,136 @@
|
||||||
|
# Generated by Django 5.0.2 on 2024-04-05 16:56
|
||||||
|
|
||||||
|
import json
|
||||||
|
import wagtail.blocks
|
||||||
|
import wagtail.embeds.blocks
|
||||||
|
import wagtail.fields
|
||||||
|
import wagtail.images.blocks
|
||||||
|
|
||||||
|
from django.core.serializers.json import DjangoJSONEncoder
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
def convert_to_streamfield(apps, schema_editor):
|
||||||
|
HomePage = apps.get_model("home", "HomePage")
|
||||||
|
for page in HomePage.objects.all():
|
||||||
|
page.body = json.dumps(
|
||||||
|
[{"type": "paragraph", "value": page.body}],
|
||||||
|
cls=DjangoJSONEncoder
|
||||||
|
)
|
||||||
|
page.save()
|
||||||
|
|
||||||
|
|
||||||
|
def convert_to_richtext(apps, schema_editor):
|
||||||
|
HomePage = apps.get_model("home", "HomePage")
|
||||||
|
for page in HomePage.objects.all():
|
||||||
|
if page.body:
|
||||||
|
stream = json.loads(page.body)
|
||||||
|
page.body = "".join([
|
||||||
|
child["value"] for child in stream
|
||||||
|
if child["type"] == "paragraph"
|
||||||
|
])
|
||||||
|
page.save()
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
dependencies = [
|
||||||
|
('home', '0005_homepage_canonical_url_homepage_og_image_and_more'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RunPython(
|
||||||
|
convert_to_streamfield,
|
||||||
|
convert_to_richtext,
|
||||||
|
),
|
||||||
|
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='homepage',
|
||||||
|
name='body',
|
||||||
|
field=wagtail.fields.StreamField([('heading_block', wagtail.blocks.StructBlock(
|
||||||
|
[('heading_text', wagtail.blocks.CharBlock(form_classname='title', required=True)), ('size',
|
||||||
|
wagtail.blocks.ChoiceBlock(
|
||||||
|
blank=True,
|
||||||
|
choices=[('',
|
||||||
|
'Select a heading size'),
|
||||||
|
('h2',
|
||||||
|
'H2'),
|
||||||
|
('h3',
|
||||||
|
'H3'),
|
||||||
|
('h4',
|
||||||
|
'H4')],
|
||||||
|
required=False))])),
|
||||||
|
('paragraph', wagtail.blocks.RichTextBlock(blank=True)), ('code',
|
||||||
|
wagtail.blocks.StructBlock(
|
||||||
|
[(
|
||||||
|
'language',
|
||||||
|
wagtail.blocks.ChoiceBlock(
|
||||||
|
choices=[
|
||||||
|
(
|
||||||
|
'bash',
|
||||||
|
'Bash/Shell'),
|
||||||
|
(
|
||||||
|
'css',
|
||||||
|
'CSS'),
|
||||||
|
(
|
||||||
|
'dart',
|
||||||
|
'Dart'),
|
||||||
|
(
|
||||||
|
'docker',
|
||||||
|
'Docker'),
|
||||||
|
(
|
||||||
|
'elixir',
|
||||||
|
'Elixir'),
|
||||||
|
(
|
||||||
|
'go',
|
||||||
|
'Go'),
|
||||||
|
(
|
||||||
|
'html',
|
||||||
|
'HTML'),
|
||||||
|
(
|
||||||
|
'javascript',
|
||||||
|
'Javascript'),
|
||||||
|
(
|
||||||
|
'json',
|
||||||
|
'JSON'),
|
||||||
|
(
|
||||||
|
'kotlin',
|
||||||
|
'Kotlin'),
|
||||||
|
(
|
||||||
|
'python',
|
||||||
|
'Python'),
|
||||||
|
(
|
||||||
|
'rust',
|
||||||
|
'Rust'),
|
||||||
|
(
|
||||||
|
'swift',
|
||||||
|
'Swift'),
|
||||||
|
(
|
||||||
|
'toml',
|
||||||
|
'TOML'),
|
||||||
|
(
|
||||||
|
'yaml',
|
||||||
|
'YAML')],
|
||||||
|
help_text='Coding language',
|
||||||
|
identifier='language',
|
||||||
|
label='Language')),
|
||||||
|
('code',
|
||||||
|
wagtail.blocks.TextBlock(
|
||||||
|
identifier='code',
|
||||||
|
label='Code'))],
|
||||||
|
label='Code snippet')),
|
||||||
|
('blockquote', wagtail.blocks.BlockQuoteBlock()), ('image_block',
|
||||||
|
wagtail.blocks.StructBlock(
|
||||||
|
[('image',
|
||||||
|
wagtail.images.blocks.ImageChooserBlock(
|
||||||
|
required=True)),
|
||||||
|
('caption',
|
||||||
|
wagtail.blocks.CharBlock(
|
||||||
|
required=False)),
|
||||||
|
('attribution',
|
||||||
|
wagtail.blocks.CharBlock(
|
||||||
|
required=False))])),
|
||||||
|
('embed_block', wagtail.embeds.blocks.EmbedBlock(
|
||||||
|
help_text='Insert a URL to embed. For example, https://www.youtube.com/watch?v=SGJFWirQ3ks',
|
||||||
|
icon='media'))], blank=True, help_text='Write anything'),
|
||||||
|
),
|
||||||
|
]
|
|
@ -1,9 +1,10 @@
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
||||||
from wagtail.models import Page
|
from wagtail.models import Page
|
||||||
from wagtail.fields import RichTextField
|
from wagtail.fields import RichTextField, StreamField
|
||||||
from wagtail.admin.panels import FieldPanel, MultiFieldPanel
|
from wagtail.admin.panels import FieldPanel, MultiFieldPanel
|
||||||
from wagtailseo.models import SeoMixin
|
from wagtailseo.models import SeoMixin
|
||||||
|
from .blocks import HomeContentBlock
|
||||||
|
|
||||||
|
|
||||||
class HomePage(SeoMixin, Page):
|
class HomePage(SeoMixin, Page):
|
||||||
|
@ -34,7 +35,12 @@ class HomePage(SeoMixin, Page):
|
||||||
verbose_name="Hero CTA link",
|
verbose_name="Hero CTA link",
|
||||||
help_text="Choose a page to link to for the Call to Action",
|
help_text="Choose a page to link to for the Call to Action",
|
||||||
)
|
)
|
||||||
body = RichTextField(blank=True)
|
body = StreamField(
|
||||||
|
HomeContentBlock(),
|
||||||
|
blank=True,
|
||||||
|
use_json_field=True,
|
||||||
|
help_text="Write anything",
|
||||||
|
)
|
||||||
|
|
||||||
content_panels = Page.content_panels + [
|
content_panels = Page.content_panels + [
|
||||||
MultiFieldPanel(
|
MultiFieldPanel(
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
<section class="max-w-7xl px-0 md:px-4 lg:px-8">
|
<section class="max-w-7xl px-0 md:px-4 lg:px-8">
|
||||||
<div class="w-full px-2 lg:px-4">
|
<div class="w-full px-2 lg:px-4">
|
||||||
{{ page.body|richtext }}
|
{{ page.body }}
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue