{% trans "Welcome to your new Wagtail site!" %}
-{% trans " by Wagtail Starter Kit" %}
- - -diff --git a/README.md b/README.md index 3adec25..f75d9da 100644 --- a/README.md +++ b/README.md @@ -77,14 +77,17 @@ The project includes custom Django management commands to help with development For detailed documentation on all available commands, see [Management Commands Documentation](./docs/management-commands.md). -### Quick Examples +### Quick Examples (recommended running order) ```bash # Create sample images and documents for testing docker exec -it wagtail-starter-kit-app-1 python manage.py create_sample_media -# Reset all sample content -docker exec -it wagtail-starter-kit-app-1 python manage.py create_sample_media --reset +# Populate the home page with sample content +docker exec -it wagtail-starter-kit-app-1 python manage.py populate_homepage + +# Create a complete blog structure with sample posts and authors +docker exec -it wagtail-starter-kit-app-1 python manage.py populate_blog ``` ## View the site diff --git a/app/blog/__init__.py b/app/blog/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/blog/apps.py b/app/blog/apps.py new file mode 100644 index 0000000..e0e9de1 --- /dev/null +++ b/app/blog/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class BlogConfig(AppConfig): + default_auto_field = "django.db.models.BigAutoField" + name = "app.blog" diff --git a/app/blog/management/__init__.py b/app/blog/management/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/blog/management/commands/__init__.py b/app/blog/management/commands/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/blog/management/commands/populate_blog.py b/app/blog/management/commands/populate_blog.py new file mode 100644 index 0000000..bfaf936 --- /dev/null +++ b/app/blog/management/commands/populate_blog.py @@ -0,0 +1,361 @@ +import random +from datetime import date, timedelta + +from django.core.management.base import BaseCommand +from wagtail.images.models import Image + +from app.blog.models import ( + Author, + BlogIndexPage, + BlogPage, + BlogPageGalleryImage, + BlogTagIndexPage, +) +from app.home.models import HomePage + + +class Command(BaseCommand): + help = ( + "Creates a complete blog structure with sample content including blog index pages, " + "blog posts with unique titles, authors, tags, and gallery images. Can be run " + "multiple times safely to add more content without conflicts." + ) + + def add_arguments(self, parser): + parser.add_argument( + "--posts", + type=int, + default=10, + help=( + "Number of blog posts to create (default: 10). Each post will have " + "unique titles, slugs, content, authors, and tags." + ), + ) + parser.add_argument( + "--authors", + type=int, + default=3, + help=( + "Number of authors to create (default: 3). If authors already exist, " + "they will be reused instead of creating new ones." + ), + ) + parser.add_argument( + "--clear", + action="store_true", + help=( + "Clear existing blog content (posts and index pages) before creating " + "new content. Authors are preserved to maintain relationships." + ), + ) + + def handle(self, *args, **options): + try: + # Get the home page + home_page = HomePage.objects.first() + if not home_page: + self.stdout.write( + self.style.ERROR( + "No home page found. Please create a home page first." + ) + ) + return + + # Clear existing content if requested + if options["clear"]: + self.clear_blog_content() + self.clear_authors() + self.clear_tags() + # Refresh home page from database after clearing content + home_page.refresh_from_db() + + # Create or get blog index page + blog_index = self.create_blog_index(home_page) + + # Create blog tag index page + self.create_blog_tag_index(home_page) + + # Create sample authors + authors = self.create_authors(options["authors"]) + + # Create blog posts + self.create_blog_posts(blog_index, authors, options["posts"]) + + self.stdout.write( + self.style.SUCCESS( + f"Successfully created blog structure with {options['posts']} posts " + f"and {len(authors)} authors" + ) + ) + + except Exception as e: + self.stdout.write(self.style.ERROR(f"An error occurred: {str(e)}")) + + def clear_blog_content(self): + """Clear existing blog content""" + + # Then delete the index pages, children also deleted + blog_indices = BlogIndexPage.objects.all() + for index in blog_indices: + index.delete() + self.stdout.write("Cleared existing blog index pages") + + tag_indices = BlogTagIndexPage.objects.all() + for tag_index in tag_indices: + tag_index.delete() + self.stdout.write("Cleared existing blog tag pages") + + def clear_authors(self): + """Clear all authors""" + Author.objects.all().delete() + self.stdout.write("Cleared all authors") + + def clear_tags(self): + """Clear all blog tags""" + BlogPage.tags.through.objects.all().delete() + self.stdout.write("Cleared all blog tags") + + def create_blog_index(self, home_page): + """Create or get the blog index page""" + # Try to get existing blog index that's a child of home page + blog_index = home_page.get_children().type(BlogIndexPage).first() + + if not blog_index: + blog_index = BlogIndexPage( + title="Blog", + slug="blog", + intro=( + "
Welcome to our blog! Here you'll find the latest news, " + "insights, and stories from our team.
" + ), + ) + home_page.add_child(instance=blog_index) + blog_index.save_revision().publish() + self.stdout.write("Created blog index page") + else: + self.stdout.write("Blog index page already exists") + + return blog_index + + def create_blog_tag_index(self, home_page): + """Create or get the blog tag index page""" + # Try to get existing blog tag index that's a child of home page + tag_index = home_page.get_children().type(BlogTagIndexPage).first() + + if not tag_index: + tag_index = BlogTagIndexPage( + title="Blog Tags", + slug="blog-tags", + ) + home_page.add_child(instance=tag_index) + tag_index.save_revision().publish() + self.stdout.write("Created blog tag index page") + else: + self.stdout.write("Blog tag index page already exists") + + return tag_index + + def create_authors(self, num_authors): + """Create sample authors""" + existing_authors = Author.objects.all() + if existing_authors.exists(): + self.stdout.write(f"Using {existing_authors.count()} existing authors") + return list(existing_authors) + + author_names = [ + "Alice Johnson", + "Bob Smith", + "Carol Davis", + "David Wilson", + "Eva Brown", + "Frank Miller", + "Grace Lee", + "Henry Taylor", + "Ivy Chen", + "Jack Thompson", + ] + + authors = [] + available_images = list(Image.objects.all()) + + for i in range(min(num_authors, len(author_names))): + author = Author.objects.create( + name=author_names[i], + author_image=( + random.choice(available_images) if available_images else None + ), + ) + authors.append(author) + + self.stdout.write(f"Created {len(authors)} authors") + return authors + + def create_blog_posts(self, blog_index, authors, num_posts): + """Create sample blog posts""" + + # Sample blog post data + post_topics = [ + "Getting Started with Wagtail CMS", + "Building Modern Web Applications", + "The Future of Content Management", + "Django Development Best Practices", + "Responsive Web Design Tips", + "SEO Optimization Strategies", + "User Experience Design Principles", + "Digital Marketing Trends", + "Web Performance Optimization", + "Accessibility in Web Development", + "Progressive Web Applications", + "API Design and Development", + "Database Optimization Techniques", + "Security Best Practices", + "DevOps and Deployment Strategies", + ] + + blog_tags = [ + "wagtail", + "django", + "python", + "web-development", + "cms", + "frontend", + "backend", + "design", + "ux", + "seo", + "performance", + "security", + "api", + "database", + "devops", + ] + + available_images = list(Image.objects.all()) + + for i in range(num_posts): + # Generate unique blog post content + topic = post_topics[i % len(post_topics)] + post_date = date.today() - timedelta(days=random.randint(1, 365)) + + # Select random authors (1-3 authors per post) + post_authors = random.sample( + authors, k=random.randint(1, min(3, len(authors))) + ) + + # Select random tags (2-4 tags per post) + post_tags = random.sample(blog_tags, k=random.randint(2, 4)) + + # Generate unique title + unique_title = f"{topic} - {post_date.strftime('%B %Y')} Edition" + intro = self.generate_intro(topic) + body = self.generate_body(topic) + + blog_post = blog_index.add_child( + instance=BlogPage( + title=unique_title, + date=post_date, + intro=intro, + body=body, + ) + ) + + # Add authors + blog_post.authors.set(post_authors) + + # Add tags + for tag in post_tags: + blog_post.tags.add(tag) + + # Add gallery images (1-6 images per post) + if available_images: + num_images = random.randint(1, min(6, len(available_images))) + selected_images = random.sample(available_images, k=num_images) + + for idx, image in enumerate(selected_images): + BlogPageGalleryImage.objects.create( + page=blog_post, + image=image, + caption=f"Image {idx + 1} for {blog_post.title}", + ) + + revision = blog_post.save_revision() + revision.publish() + + self.stdout.write(f"Created {num_posts} blog posts") + + def generate_intro(self, topic): + """Generate sample introduction for blog post""" + intros = { + "Getting Started with Wagtail CMS": ( + "Learn the basics of Wagtail CMS and how to build your first " + "content-driven website with this powerful Django-based platform." + ), + "Building Modern Web Applications": ( + "Explore the latest techniques and tools for creating responsive, " + "scalable web applications that meet today's user expectations." + ), + "The Future of Content Management": ( + "Discover emerging trends in content management systems and how " + "they're shaping the digital landscape." + ), + "Django Development Best Practices": ( + "Master the art of Django development with proven patterns, " + "conventions, and techniques used by experienced developers." + ), + "Responsive Web Design Tips": ( + "Create websites that look great on any device with these essential " + "responsive design principles and practical implementation tips." + ), + } + return intros.get( + topic, + f"An in-depth look at {topic.lower()} and its practical applications " + f"in modern web development.", + ) + + def generate_body(self, topic): + """Generate sample body content for blog post""" + return f""" +In this comprehensive guide, we'll explore {topic.lower()} and its + importance in modern web development. Whether you're a beginner or an experienced developer, + this article will provide valuable insights and practical examples.
+ +Understanding the fundamental concepts is crucial for success. We'll cover the most + important aspects that every developer should know about this topic.
+ +Let's dive into the practical implementation details. This section provides step-by-step + instructions and code examples to help you get started.
+ +The implementation process involves several key steps:
+For those looking to take their skills to the next level, here are some advanced + techniques and considerations that can make a significant difference in your projects.
+ +By following the guidelines and best practices outlined in this article, you'll be + well-equipped to tackle {topic.lower()} in your own projects. Remember to + keep learning and stay updated with the latest developments in the field.
+ +Happy coding!
+ """.strip() diff --git a/app/blog/migrations/0001_initial.py b/app/blog/migrations/0001_initial.py new file mode 100644 index 0000000..8978d32 --- /dev/null +++ b/app/blog/migrations/0001_initial.py @@ -0,0 +1,38 @@ +# Generated by Django 5.1.1 on 2024-10-06 12:26 + +import django.db.models.deletion +import wagtail.fields +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ("wagtailcore", "0094_alter_page_locale"), + ] + + operations = [ + migrations.CreateModel( + name="BlogIndexPage", + fields=[ + ( + "page_ptr", + models.OneToOneField( + auto_created=True, + on_delete=django.db.models.deletion.CASCADE, + parent_link=True, + primary_key=True, + serialize=False, + to="wagtailcore.page", + ), + ), + ("intro", wagtail.fields.RichTextField(blank=True)), + ], + options={ + "abstract": False, + }, + bases=("wagtailcore.page",), + ), + ] diff --git a/app/blog/migrations/0002_blogpage.py b/app/blog/migrations/0002_blogpage.py new file mode 100644 index 0000000..816ec55 --- /dev/null +++ b/app/blog/migrations/0002_blogpage.py @@ -0,0 +1,39 @@ +# Generated by Django 5.1.1 on 2024-10-06 12:31 + +import django.db.models.deletion +import wagtail.fields +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("blog", "0001_initial"), + ("wagtailcore", "0094_alter_page_locale"), + ] + + operations = [ + migrations.CreateModel( + name="BlogPage", + fields=[ + ( + "page_ptr", + models.OneToOneField( + auto_created=True, + on_delete=django.db.models.deletion.CASCADE, + parent_link=True, + primary_key=True, + serialize=False, + to="wagtailcore.page", + ), + ), + ("date", models.DateField(verbose_name="Post date")), + ("intro", models.CharField(max_length=250)), + ("body", wagtail.fields.RichTextField(blank=True)), + ], + options={ + "abstract": False, + }, + bases=("wagtailcore.page",), + ), + ] diff --git a/app/blog/migrations/0003_blogpagegalleryimage.py b/app/blog/migrations/0003_blogpagegalleryimage.py new file mode 100644 index 0000000..7b75e12 --- /dev/null +++ b/app/blog/migrations/0003_blogpagegalleryimage.py @@ -0,0 +1,55 @@ +# Generated by Django 5.1.1 on 2024-10-06 12:46 + +import django.db.models.deletion +import modelcluster.fields +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("blog", "0002_blogpage"), + ("wagtailimages", "0026_delete_uploadedimage"), + ] + + operations = [ + migrations.CreateModel( + name="BlogPageGalleryImage", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "sort_order", + models.IntegerField(blank=True, editable=False, null=True), + ), + ("caption", models.CharField(blank=True, max_length=250)), + ( + "image", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="+", + to="wagtailimages.image", + ), + ), + ( + "page", + modelcluster.fields.ParentalKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="gallery_images", + to="blog.blogpage", + ), + ), + ], + options={ + "ordering": ["sort_order"], + "abstract": False, + }, + ), + ] diff --git a/app/blog/migrations/0004_author.py b/app/blog/migrations/0004_author.py new file mode 100644 index 0000000..6c63a3d --- /dev/null +++ b/app/blog/migrations/0004_author.py @@ -0,0 +1,43 @@ +# Generated by Django 5.1.1 on 2024-10-06 20:11 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("blog", "0003_blogpagegalleryimage"), + ("wagtailimages", "0026_delete_uploadedimage"), + ] + + operations = [ + migrations.CreateModel( + name="Author", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("name", models.CharField(max_length=255)), + ( + "author_image", + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="+", + to="wagtailimages.image", + ), + ), + ], + options={ + "verbose_name_plural": "Authors", + }, + ), + ] diff --git a/app/blog/migrations/0005_blogpage_authors.py b/app/blog/migrations/0005_blogpage_authors.py new file mode 100644 index 0000000..e0e4965 --- /dev/null +++ b/app/blog/migrations/0005_blogpage_authors.py @@ -0,0 +1,21 @@ +# Generated by Django 5.1.1 on 2024-10-06 20:15 + +import modelcluster.fields +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ("blog", "0004_author"), + ] + + operations = [ + migrations.AddField( + model_name="blogpage", + name="authors", + field=modelcluster.fields.ParentalManyToManyField( + blank=True, to="blog.author" + ), + ), + ] diff --git a/app/blog/migrations/0006_blogpagetag_blogpage_tags.py b/app/blog/migrations/0006_blogpagetag_blogpage_tags.py new file mode 100644 index 0000000..fc4b7b6 --- /dev/null +++ b/app/blog/migrations/0006_blogpagetag_blogpage_tags.py @@ -0,0 +1,64 @@ +# Generated by Django 5.1.1 on 2024-10-06 20:23 + +import django.db.models.deletion +import modelcluster.contrib.taggit +import modelcluster.fields +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("blog", "0005_blogpage_authors"), + ( + "taggit", + "0006_rename_taggeditem_content_type_object_id_taggit_tagg_content_8fc721_idx", + ), + ] + + operations = [ + migrations.CreateModel( + name="BlogPageTag", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "content_object", + modelcluster.fields.ParentalKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="tagged_items", + to="blog.blogpage", + ), + ), + ( + "tag", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="%(app_label)s_%(class)s_items", + to="taggit.tag", + ), + ), + ], + options={ + "abstract": False, + }, + ), + migrations.AddField( + model_name="blogpage", + name="tags", + field=modelcluster.contrib.taggit.ClusterTaggableManager( + blank=True, + help_text="A comma-separated list of tags.", + through="blog.BlogPageTag", + to="taggit.Tag", + verbose_name="Tags", + ), + ), + ] diff --git a/app/blog/migrations/0007_blogtagindexpage.py b/app/blog/migrations/0007_blogtagindexpage.py new file mode 100644 index 0000000..0087249 --- /dev/null +++ b/app/blog/migrations/0007_blogtagindexpage.py @@ -0,0 +1,35 @@ +# Generated by Django 5.1.1 on 2024-10-06 20:31 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("blog", "0006_blogpagetag_blogpage_tags"), + ("wagtailcore", "0094_alter_page_locale"), + ] + + operations = [ + migrations.CreateModel( + name="BlogTagIndexPage", + fields=[ + ( + "page_ptr", + models.OneToOneField( + auto_created=True, + on_delete=django.db.models.deletion.CASCADE, + parent_link=True, + primary_key=True, + serialize=False, + to="wagtailcore.page", + ), + ), + ], + options={ + "abstract": False, + }, + bases=("wagtailcore.page",), + ), + ] diff --git a/app/blog/migrations/__init__.py b/app/blog/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/blog/models.py b/app/blog/models.py new file mode 100644 index 0000000..76c8e66 --- /dev/null +++ b/app/blog/models.py @@ -0,0 +1,113 @@ +from django import forms +from django.db import models +from modelcluster.contrib.taggit import ClusterTaggableManager +from modelcluster.fields import ParentalKey, ParentalManyToManyField +from taggit.models import TaggedItemBase +from wagtail.admin.panels import FieldPanel, InlinePanel, MultiFieldPanel +from wagtail.fields import RichTextField +from wagtail.models import Orderable, Page +from wagtail.search import index +from wagtail.snippets.models import register_snippet + + +class BlogIndexPage(Page): + intro = RichTextField(blank=True) + + content_panels = Page.content_panels + [FieldPanel("intro")] + + def get_context(self, request): + # Update context to include only published posts, ordered by reverse-chron + context = super().get_context(request) + blogpages = self.get_children().live().order_by("-first_published_at") + context["blogpages"] = blogpages + return context + + +class BlogPageTag(TaggedItemBase): + content_object = ParentalKey( + "BlogPage", related_name="tagged_items", on_delete=models.CASCADE + ) + + +class BlogPage(Page): + date = models.DateField("Post date") + intro = models.CharField(max_length=250) + body = RichTextField(blank=True) + authors = ParentalManyToManyField("blog.Author", blank=True) + tags = ClusterTaggableManager(through=BlogPageTag, blank=True) + + search_fields = Page.search_fields + [ + index.SearchField("intro"), + index.SearchField("body"), + ] + + content_panels = Page.content_panels + [ + MultiFieldPanel( + [ + FieldPanel("date"), + FieldPanel("authors", widget=forms.CheckboxSelectMultiple), + FieldPanel("tags"), + ], + heading="Blog information", + ), + FieldPanel("intro"), + FieldPanel("body"), + InlinePanel("gallery_images", label="Gallery images"), + ] + + def main_image(self): + gallery_item = self.gallery_images.first() + if gallery_item: + return gallery_item.image + else: + return None + + +class BlogPageGalleryImage(Orderable): + page = ParentalKey( + BlogPage, on_delete=models.CASCADE, related_name="gallery_images" + ) + image = models.ForeignKey( + "wagtailimages.Image", on_delete=models.CASCADE, related_name="+" + ) + caption = models.CharField(blank=True, max_length=250) + + panels = [ + FieldPanel("image"), + FieldPanel("caption"), + ] + + +@register_snippet +class Author(models.Model): + name = models.CharField(max_length=255) + author_image = models.ForeignKey( + "wagtailimages.Image", + null=True, + blank=True, + on_delete=models.SET_NULL, + related_name="+", + ) + + panels = [ + FieldPanel("name"), + FieldPanel("author_image"), + ] + + class Meta: + verbose_name_plural = "Authors" + + def __str__(self): + return self.name + + +class BlogTagIndexPage(Page): + def get_context(self, request): + # Filter by tag + tag = request.GET.get("tag") + blogpages = BlogPage.objects.filter(tags__name=tag) + + # Update template context + context = super().get_context(request) + context["blogpages"] = blogpages + return context diff --git a/app/blog/templates/blog/blog_index_page.html b/app/blog/templates/blog/blog_index_page.html new file mode 100644 index 0000000..f208bca --- /dev/null +++ b/app/blog/templates/blog/blog_index_page.html @@ -0,0 +1,48 @@ +{% extends "base.html" %} + +{% load wagtailcore_tags wagtailimages_tags %} + +{% block body_class %}template-blogindexpage{% endblock %} + +{% block content %} +{{ post.intro }}
+ {{ post.body|richtext }} +Posted by:
+ {% for author in authors %} + + {% image author.author_image fill-40x40 as author_image %} + {% if author_image %} +Create a blog tags page
+ {% endif %} + {% endif %} + {% endwith %} +{{ page.intro }}
+ {{ page.body|richtext }} + + +This is your homepage, built with Wagtail CMS. Wagtail is a powerful, +developer-friendly content management system built on Django that makes it easy to create +beautiful, engaging websites.
+ +{image_embed} + +You can edit this content by going to the Wagtail admin and +selecting your home page. From there, you can:
+ +This starter kit includes:
+ +Now that you have your site running, consider:
+ +Happy building with Wagtail!
+ """.strip() + + # Update the home page body content + home_page.body = sample_content + home_page.save() + + # Create a new revision to track the change + home_page.save_revision().publish() + + success_message = f"Successfully populated home page body content ({len(sample_content)} characters)" + if selected_image: + success_message += f" with image: {selected_image.title}" + + self.stdout.write(self.style.SUCCESS(success_message)) + + except HomePage.DoesNotExist: + self.stdout.write( + self.style.ERROR("No home page found. Please create a home page first.") + ) + except Exception as e: + self.stdout.write(self.style.ERROR(f"An error occurred: {str(e)}")) diff --git a/app/home/migrations/0003_homepage_body.py b/app/home/migrations/0003_homepage_body.py new file mode 100644 index 0000000..7a81014 --- /dev/null +++ b/app/home/migrations/0003_homepage_body.py @@ -0,0 +1,19 @@ +# Generated by Django 5.1.1 on 2024-10-06 12:19 + +import wagtail.fields +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ("home", "0002_create_homepage"), + ] + + operations = [ + migrations.AddField( + model_name="homepage", + name="body", + field=wagtail.fields.RichTextField(blank=True), + ), + ] diff --git a/app/home/models.py b/app/home/models.py index a8a0cc2..fe0adbe 100644 --- a/app/home/models.py +++ b/app/home/models.py @@ -1,9 +1,11 @@ -from wagtail import __version__ as WAGTAIL_VERSION +from wagtail.admin.panels import FieldPanel +from wagtail.fields import RichTextField from wagtail.models import Page class HomePage(Page): - def get_context(self, request): - context = super().get_context(request) - context["wagtail_version"] = WAGTAIL_VERSION - return context + body = RichTextField(blank=True) + + content_panels = Page.content_panels + [ + FieldPanel("body"), + ] diff --git a/app/home/templates/home/home_page.html b/app/home/templates/home/home_page.html index 0b1dc65..86b072e 100644 --- a/app/home/templates/home/home_page.html +++ b/app/home/templates/home/home_page.html @@ -1,143 +1,15 @@ {% extends "base.html" %} -{% load static %} - -{% block body_class %}template-homepage{% endblock %} - -{% block extra_css %} - -{% comment %} -Delete the line below if you're just getting started and want to remove the welcome screen! -{% endcomment %} - -{% endblock extra_css %} +{% block body_class %}template-homepage{% endblock %} {% block content %} - -{% comment %} -Delete the line below if you're just getting started and want to remove the welcome screen! -{% endcomment %} -{% include 'home/welcome_page.html' %} - -{% endblock content %} +No content has been added to this page body yet.
+ {% endif %} +{% trans " by Wagtail Starter Kit" %}
- - -