The Wagtail Bakery Demo follows Django’s standard project structure with Wagtail-specific additions. This guide explains the purpose of each directory and file.
Root Directory Structure
wagtail-bakery-demo/
├── bakerydemo/ # Main Django project package
├── manage.py # Django management script
├── requirements/ # Python dependencies
├── requirements.txt # Main requirements file
├── Dockerfile # Docker container configuration
├── docker-compose.yml # Docker services configuration
├── .env.example # Environment variables template
├── package.json # Frontend dependencies (npm)
├── ruff.toml # Python linter configuration
└── readme.md # Project documentation
The bakerydemo Package
The main project package contains all Django apps and configuration:
bakerydemo/
├── __init__.py
├── settings/ # Settings modules
├── urls.py # URL configuration
├── wsgi.py # WSGI application
├── api.py # API router configuration
├── base/ # Core app
├── blog/ # Blog functionality
├── breads/ # Bread catalog
├── recipes/ # Recipe pages
├── locations/ # Bakery locations
├── people/ # Person model
├── search/ # Search functionality
├── templates/ # Global templates
├── static/ # Static files (CSS, JS, images)
└── media/ # User-uploaded files
Key Files Explained
manage.py
The Django management script is your primary interface for running commands:
#!/usr/bin/env python
import os
import sys
import dotenv
if __name__ == "__main__" :
dotenv.load_dotenv() # Load environment variables from .env
os.environ.setdefault( "DJANGO_SETTINGS_MODULE" , "bakerydemo.settings.dev" )
from django.core.management import execute_from_command_line
execute_from_command_line(sys.argv)
The manage.py file loads environment variables from .env and defaults to development settings.
urls.py
The main URL configuration routes requests to appropriate views:
from django.urls import include, path
from wagtail import urls as wagtail_urls
from wagtail.admin import urls as wagtailadmin_urls
urlpatterns = [
path( "django-admin/" , admin.site.urls), # Django admin
path( "admin/" , include(wagtailadmin_urls)), # Wagtail admin
path( "documents/" , include(wagtaildocs_urls)),
path( "search/" , search_views.search, name = "search" ),
path( "sitemap.xml" , sitemap),
path( "api/v2/" , api_router.urls), # REST API
path( "" , include(wagtail_urls)), # Wagtail pages (catch-all)
]
Django Admin
Located at /django-admin/ - provides access to Django’s built-in admin interface for low-level model management.
Wagtail Admin
Located at /admin/ - the primary content editing interface with Wagtail’s user-friendly experience.
API Endpoints
Located at /api/v2/ - RESTful API for accessing pages, images, and documents programmatically.
Page Routing
The catch-all pattern at the end routes all other URLs through Wagtail’s page tree structure.
api.py
Configures the Wagtail API endpoints:
from wagtail.api.v2.router import WagtailAPIRouter
from wagtail.api.v2.views import PagesAPIViewSet
from wagtail.documents.api.v2.views import DocumentsAPIViewSet
from wagtail.images.api.v2.views import ImagesAPIViewSet
api_router = WagtailAPIRouter( "wagtailapi" )
api_router.register_endpoint( "pages" , PagesAPIViewSet)
api_router.register_endpoint( "images" , ImagesAPIViewSet)
api_router.register_endpoint( "documents" , DocumentsAPIViewSet)
wsgi.py
WSGI application for production deployment:
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault( "DJANGO_SETTINGS_MODULE" , "bakerydemo.settings.production" )
application = get_wsgi_application()
Settings Directory
Settings are split into multiple files for different environments:
settings/
├── __init__.py
├── base.py # Common settings
├── dev.py # Development settings
├── production.py # Production settings
├── test.py # Test settings
└── local.py.example # Local overrides template
base.py Structure
The base settings file contains configuration shared across all environments:
PROJECT_DIR = os.path.dirname(os.path.dirname(os.path.abspath( __file__ )))
BASE_DIR = os.path.dirname( PROJECT_DIR )
Lists all Django apps in order:
Project apps (bakerydemo.base, blog, etc.)
Wagtail apps
Third-party apps (modelcluster, taggit)
Django contrib apps
MIDDLEWARE = [
"django.middleware.security.SecurityMiddleware" ,
"django.contrib.sessions.middleware.SessionMiddleware" ,
"django.middleware.common.CommonMiddleware" ,
"django.middleware.csrf.CsrfViewMiddleware" ,
"django.contrib.auth.middleware.AuthenticationMiddleware" ,
"django.contrib.messages.middleware.MessageMiddleware" ,
"django.middleware.clickjacking.XFrameOptionsMiddleware" ,
"wagtail.contrib.redirects.middleware.RedirectMiddleware" ,
]
if "DATABASE_URL" in os.environ:
DATABASES = { "default" : dj_database_url.config( conn_max_age = 500 )}
else :
DATABASES = {
"default" : {
"ENGINE" : "django.db.backends.sqlite3" ,
"NAME" : os.path.join( BASE_DIR , "bakerydemodb" ),
}
}
STATICFILES_DIRS = [os.path.join( PROJECT_DIR , "static" )]
STATIC_ROOT = os.path.join( PROJECT_DIR , "collect_static" )
STATIC_URL = "/static/"
MEDIA_ROOT = os.path.join( PROJECT_DIR , "media" )
MEDIA_URL = "/media/"
WAGTAIL_SITE_NAME = "The Wagtail Bakery"
WAGTAIL_I18N_ENABLED = True
WAGTAIL_CONTENT_LANGUAGES = LANGUAGES = [
( "en" , "English" ),
( "de" , "Deutsch" ),
( "ar" , "العربيّة" ),
]
Django App Structure
Each Django app follows a consistent structure:
app_name/
├── __init__.py
├── models.py # Data models
├── blocks.py # StreamField blocks (optional)
├── views.py # View functions (optional)
├── admin.py # Django admin config (optional)
├── wagtail_hooks.py # Wagtail admin customizations (optional)
├── templatetags/ # Custom template tags (optional)
├── migrations/ # Database migrations
├── fixtures/ # Sample data (optional)
└── tests/ # Unit tests (optional)
Example: Base App Structure
base/
├── __init__.py
├── models.py # HomePage, StandardPage, Person, FooterText
├── blocks.py # BaseStreamBlock, CaptionedImageBlock, HeadingBlock
├── filters.py # Custom filters
├── wagtail_hooks.py # Admin customizations
├── management/
│ └── commands/ # Custom management commands
│ ├── create_random_data.py
│ ├── load_initial_data.py
│ └── reset_demo.py
├── migrations/ # Database migration files
├── fixtures/ # Initial data files
├── templatetags/ # Custom template tags
│ └── navigation_tags.py
└── tests/ # Test files
Templates Directory
Templates are organized by app and component:
templates/
├── base.html # Base template
├── 404.html # 404 error page
├── 500.html # 500 error page
├── blocks/ # StreamField block templates
│ ├── captioned_image_block.html
│ ├── heading_block.html
│ ├── blockquote.html
│ └── paragraph_block.html
├── blog/ # Blog templates
│ ├── blog_index_page.html
│ └── blog_page.html
├── breads/ # Bread templates
│ ├── breads_index_page.html
│ └── bread_page.html
├── recipes/ # Recipe templates
│ ├── recipe_index_page.html
│ └── recipe_page.html
├── locations/ # Location templates
│ ├── locations_index_page.html
│ └── location_page.html
├── tags/ # Reusable components
│ └── navigation.html
└── search/ # Search templates
└── search.html
Static Files Directory
Static assets organized by type:
static/
├── css/ # Stylesheets
│ └── bakerydemo.css
├── js/ # JavaScript files
│ └── bakerydemo.js
└── img/ # Images
├── bread-favicon.ico
└── ...
Requirements Files
Python dependencies are organized in a requirements directory:
requirements/
├── base.txt # Core dependencies
├── development.txt # Development tools
└── production.txt # Production dependencies
The root requirements.txt points to the base requirements:
Common Management Commands
The project includes custom management commands in base/management/commands/:
load_initial_data Loads sample content and images for the demo site
create_random_data Generates random test data for development
reset_demo Resets the demo site to its initial state
reset_admin_password Resets the admin user password
Run these commands with:
python manage.py load_initial_data
python manage.py create_random_data
Development vs Production Structure
Development uses SQLite and file-based media storage: bakerydemo/
├── bakerydemodb # SQLite database file
└── media/ # Local media files
Static files are served by Django’s development server. Production typically uses:
PostgreSQL database (configured via DATABASE_URL)
Cloud storage for media files (S3, GCS, etc.)
Collected static files in collect_static/
python manage.py collectstatic # Gather all static files
Docker Structure
The project includes Docker support:
├── Dockerfile # Container image definition
├── docker-compose.yml # Multi-container setup
└── docker-entrypoint.sh # Container startup script
Configuration Files
Template for environment variables: DATABASE_URL = postgres://user:pass@localhost/dbname
SECRET_KEY = your-secret-key
DJANGO_SETTINGS_MODULE = bakerydemo.settings.production
Python linter configuration for code quality
Frontend dependencies managed by npm: {
"scripts" : {
"build" : "..." ,
"start" : "..."
},
"dependencies" : { ... }
}
Next Steps
Architecture Learn about the overall architecture
Content Models Explore page models and relationships
StreamField Blocks Understand content blocks