A Django content management system with a user-friendly interface and powerful features for building websites and applications.
Flexible content field types for building dynamic page layouts. Wagtail provides specialized fields for rich content creation, with StreamField offering structured content blocks for complex page designs.
Field for rich text content with WYSIWYG editing capabilities, supporting HTML formatting, links, and embedded content.
class RichTextField(models.TextField):
"""
Field for rich text content with HTML editing.
Parameters:
editor (str): Editor configuration to use ('default', 'basic', etc.)
features (list): List of allowed editor features
**kwargs: Standard TextField parameters (max_length, blank, null, etc.)
"""
def __init__(self, *args, **kwargs):
"""Initialize RichTextField with editor configuration."""
def clone(self):
"""Create a copy of this field with the same configuration."""
def formfield(self, **kwargs):
"""Create form field with rich text widget."""
def get_searchable_content(self, value):
"""Extract searchable text content from rich text."""
def extract_references(self, value):
"""Extract references to other objects from rich text."""Flexible structured content field that allows mixing different block types in a single field, providing maximum layout flexibility.
class StreamField(models.Field):
"""
Field for structured content using blocks.
Parameters:
block_types: List of (name, block) tuples, StreamBlock instance, or block class
use_json_field: Ignored, retained for migration compatibility
block_lookup: Block definition lookup for migrations
min_num (int): Minimum number of blocks required
max_num (int): Maximum number of blocks allowed
block_counts (dict): Per-block-type count limits
collapsed (bool): Whether blocks start collapsed in admin
**kwargs: Standard field parameters (blank, null, etc.)
"""
def __init__(self, block_types, use_json_field=True, block_lookup=None, **kwargs):
"""Initialize StreamField with block configuration."""
@property
def stream_block(self):
"""Get the StreamBlock instance for this field."""
@property
def json_field(self):
"""Get underlying JSONField for storage."""
def get_internal_type(self):
"""Return the internal field type."""
def to_python(self, value):
"""Convert database value to StreamValue."""
def get_prep_value(self, value):
"""Convert StreamValue to database representation."""
def deconstruct(self):
"""Return field constructor arguments for migrations."""Base classes and utilities for creating custom content blocks.
class Block:
"""
Base class for content blocks.
All content blocks inherit from this class.
"""
def get_form_context(self, value, prefix='', errors=None):
"""Get context for rendering the block's form."""
def render(self, value, context=None):
"""Render the block with the given value."""
def get_api_representation(self, value, context=None):
"""Get API representation of block value."""
class BoundBlock:
"""
Represents a block instance with a specific value.
"""
def render(self, context=None):
"""Render this block instance."""
def render_as_block(self, context=None):
"""Render with block wrapper."""
class BlockField(models.Field):
"""
Form field for block editing in admin interface.
"""
def __init__(self, block=None, **kwargs):
"""Initialize with block definition."""Basic content blocks for text, numbers, and simple data input.
class CharBlock(Block):
"""
Single line text input block.
Parameters:
required (bool): Whether the field is required
max_length (int): Maximum character length
min_length (int): Minimum character length
help_text (str): Help text for the field
validators (list): List of field validators
"""
def __init__(self, required=True, help_text=None, max_length=None, min_length=None, validators=(), **kwargs):
"""Initialize CharBlock with validation options."""
class TextBlock(Block):
"""
Multi-line text input block.
Parameters:
required (bool): Whether the field is required
rows (int): Number of textarea rows
help_text (str): Help text for the field
validators (list): List of field validators
"""
def __init__(self, required=True, help_text=None, rows=1, validators=(), **kwargs):
"""Initialize TextBlock with display options."""
class EmailBlock(Block):
"""
Email address input with validation.
"""
def __init__(self, required=True, help_text=None, validators=(), **kwargs):
"""Initialize EmailBlock with email validation."""
class IntegerBlock(Block):
"""
Integer number input block.
Parameters:
required (bool): Whether the field is required
max_value (int): Maximum allowed value
min_value (int): Minimum allowed value
"""
def __init__(self, required=True, help_text=None, max_value=None, min_value=None, validators=(), **kwargs):
"""Initialize IntegerBlock with numeric constraints."""
class FloatBlock(Block):
"""
Floating point number input block.
"""
def __init__(self, required=True, help_text=None, max_value=None, min_value=None, validators=(), **kwargs):
"""Initialize FloatBlock with numeric constraints."""
class DecimalBlock(Block):
"""
Decimal number input with precision control.
Parameters:
max_digits (int): Maximum number of digits
decimal_places (int): Number of decimal places
"""
def __init__(self, required=True, help_text=None, max_digits=None, decimal_places=None, validators=(), **kwargs):
"""Initialize DecimalBlock with precision settings."""
class RegexBlock(Block):
"""
Text input with regular expression validation.
Parameters:
regex (str): Regular expression pattern
error_message (str): Custom error message for validation failure
"""
def __init__(self, regex, error_message=None, required=True, help_text=None, validators=(), **kwargs):
"""Initialize RegexBlock with pattern validation."""
class URLBlock(Block):
"""
URL input with validation.
"""
def __init__(self, required=True, help_text=None, validators=(), **kwargs):
"""Initialize URLBlock with URL validation."""
class BooleanBlock(Block):
"""
Boolean true/false checkbox block.
"""
def __init__(self, required=True, help_text=None, **kwargs):
"""Initialize BooleanBlock."""
class DateBlock(Block):
"""
Date picker block.
Parameters:
format (str): Date format string
"""
def __init__(self, required=True, help_text=None, format=None, validators=(), **kwargs):
"""Initialize DateBlock with date formatting."""
class TimeBlock(Block):
"""
Time picker block.
Parameters:
format (str): Time format string
"""
def __init__(self, required=True, help_text=None, format=None, validators=(), **kwargs):
"""Initialize TimeBlock with time formatting."""
class DateTimeBlock(Block):
"""
Date and time picker block.
Parameters:
format (str): DateTime format string
"""
def __init__(self, required=True, help_text=None, format=None, validators=(), **kwargs):
"""Initialize DateTimeBlock with datetime formatting."""Advanced blocks for rich content, HTML, and embedded media.
class RichTextBlock(Block):
"""
Rich text editor block with formatting capabilities.
Parameters:
editor (str): Editor configuration to use
features (list): Allowed editor features
"""
def __init__(self, editor='default', features=None, **kwargs):
"""Initialize RichTextBlock with editor settings."""
class RawHTMLBlock(Block):
"""
Raw HTML content block for custom markup.
"""
def __init__(self, **kwargs):
"""Initialize RawHTMLBlock."""
class BlockQuoteBlock(Block):
"""
Block quote formatting block.
"""
def __init__(self, **kwargs):
"""Initialize BlockQuoteBlock."""
class EmbedBlock(Block):
"""
Embedded content block for videos, social media, etc.
"""
def __init__(self, **kwargs):
"""Initialize EmbedBlock for external content."""Blocks for single and multiple selection from predefined options.
class ChoiceBlock(Block):
"""
Single selection dropdown block.
Parameters:
choices (list): List of (value, label) tuples
"""
def __init__(self, choices=(), **kwargs):
"""Initialize ChoiceBlock with selection options."""
class MultipleChoiceBlock(Block):
"""
Multiple selection checkbox block.
Parameters:
choices (list): List of (value, label) tuples
"""
def __init__(self, choices=(), **kwargs):
"""Initialize MultipleChoiceBlock with selection options."""Blocks for selecting related content like pages, images, and documents.
class PageChooserBlock(Block):
"""
Page selection block with search interface.
Parameters:
page_type (str): Limit selection to specific page types
can_choose_root (bool): Whether root page can be selected
"""
def __init__(self, page_type=None, can_choose_root=False, **kwargs):
"""Initialize PageChooserBlock with type constraints."""
class DocumentChooserBlock(Block):
"""
Document selection block.
"""
def __init__(self, **kwargs):
"""Initialize DocumentChooserBlock."""
class ImageChooserBlock(Block):
"""
Image selection block.
"""
def __init__(self, **kwargs):
"""Initialize ImageChooserBlock."""
class SnippetChooserBlock(Block):
"""
Snippet selection block.
Parameters:
target_model (Model): Snippet model to choose from
"""
def __init__(self, target_model, **kwargs):
"""Initialize SnippetChooserBlock with model constraint."""Container blocks for organizing and grouping other blocks.
class StreamBlock(Block):
"""
Container for multiple different block types in sequence.
Parameters:
local_blocks (list): List of allowed child block types
min_num (int): Minimum number of child blocks
max_num (int): Maximum number of child blocks
block_counts (dict): Per-block-type count limits
"""
def __init__(self, local_blocks=(), min_num=None, max_num=None, block_counts=None, **kwargs):
"""Initialize StreamBlock with child block configuration."""
class ListBlock(Block):
"""
Container for repeated instances of a single block type.
Parameters:
child_block (Block): Block type to repeat
min_num (int): Minimum number of items
max_num (int): Maximum number of items
"""
def __init__(self, child_block, min_num=None, max_num=None, **kwargs):
"""Initialize ListBlock with child block type."""
class StructBlock(Block):
"""
Container for a fixed group of named blocks.
Parameters:
local_blocks (list): List of (name, block) tuples defining the structure
"""
def __init__(self, local_blocks=(), **kwargs):
"""Initialize StructBlock with named child blocks."""
class StaticBlock(Block):
"""
Placeholder block with no editable content.
Used for fixed content or separators in StreamField.
"""
def __init__(self, admin_text=None, template=None, **kwargs):
"""Initialize StaticBlock with display text."""Value containers that hold block content and provide rendering methods.
class StreamValue:
"""
Value container for StreamField content.
Behaves like a list of block instances.
"""
def __iter__(self):
"""Iterate over block instances."""
def __len__(self):
"""Get number of blocks."""
def __getitem__(self, index):
"""Get block at index."""
def render(self, context=None):
"""Render all blocks as HTML."""
class ListValue:
"""
Value container for ListBlock content.
"""
def __iter__(self):
"""Iterate over list items."""
def __len__(self):
"""Get number of items."""
def render(self, context=None):
"""Render all items as HTML."""
class StructValue:
"""
Value container for StructBlock content.
Provides attribute-style access to named blocks.
"""
def __getitem__(self, key):
"""Get block value by name."""
def render(self, context=None):
"""Render all blocks as HTML."""from wagtail.models import Page
from wagtail.fields import StreamField
from wagtail.blocks import CharBlock, TextBlock, RichTextBlock, ImageChooserBlock, StructBlock
from wagtail.admin.panels import FieldPanel
class HomePage(Page):
"""Homepage with flexible content blocks."""
# Define custom blocks
class HeroBlock(StructBlock):
title = CharBlock(max_length=200)
subtitle = TextBlock(max_length=400)
background_image = ImageChooserBlock()
call_to_action = CharBlock(max_length=100)
class Meta:
template = 'blocks/hero.html'
icon = 'image'
# StreamField with mixed content types
content = StreamField([
('hero', HeroBlock()),
('paragraph', RichTextBlock()),
('image', ImageChooserBlock()),
('quote', BlockQuoteBlock()),
], use_json_field=True)
content_panels = Page.content_panels + [
FieldPanel('content'),
]from wagtail.blocks import ListBlock, StructBlock, CharBlock, IntegerBlock, ChoiceBlock
class TestimonialBlock(StructBlock):
"""Structured block for customer testimonials."""
quote = TextBlock(max_length=500)
author = CharBlock(max_length=100)
company = CharBlock(max_length=100, required=False)
rating = IntegerBlock(min_value=1, max_value=5)
class Meta:
template = 'blocks/testimonial.html'
icon = 'user'
class FeatureBlock(StructBlock):
"""Feature highlight block."""
title = CharBlock(max_length=100)
description = RichTextBlock(features=['bold', 'italic', 'link'])
icon = ChoiceBlock(choices=[
('star', 'Star'),
('heart', 'Heart'),
('check', 'Check'),
])
class Meta:
template = 'blocks/feature.html'
# Using blocks in StreamField
content = StreamField([
('testimonials', ListBlock(TestimonialBlock())),
('features', ListBlock(FeatureBlock(), max_num=6)),
], use_json_field=True)from wagtail.fields import RichTextField
class ArticlePage(Page):
"""Article page with different rich text configurations."""
# Full-featured rich text editor
body = RichTextField(
features=[
'h2', 'h3', 'h4', 'bold', 'italic', 'link', 'ol', 'ul',
'document-link', 'image', 'embed', 'code', 'superscript', 'subscript'
]
)
# Simple rich text for summaries
summary = RichTextField(
features=['bold', 'italic', 'link'],
max_length=500
)
# Basic editor for captions
caption = RichTextField(
editor='basic',
features=['bold', 'italic'],
max_length=200
)from wagtail.blocks import Block
from django import forms
class ColorBlock(Block):
"""Custom block for color picker."""
def get_form_context(self, value, prefix='', errors=None):
context = super().get_form_context(value, prefix, errors)
context['widget'] = forms.TextInput(attrs={
'type': 'color',
'class': 'color-picker'
})
return context
def render(self, value, context=None):
return f'<div style="background-color: {value}; height: 50px;"></div>'
class Meta:
icon = 'image'
template = 'blocks/color.html'
# Using custom block
class DesignPage(Page):
color_scheme = StreamField([
('color', ColorBlock()),
('text', RichTextBlock()),
])Install with Tessl CLI
npx tessl i tessl/pypi-wagtail