StreamField Blocks
==================
Django Cast uses Wagtail's StreamField to provide flexible content editing. Posts and Episodes have a ``body`` field with two sections: ``overview`` (summary) and ``detail`` (full content). Both sections support the same built-in content blocks, and projects can append custom blocks with ``CAST_POST_BODY_BLOCKS``.
Overview
--------
The StreamField structure allows authors to create dynamic content layouts by combining different block types. Each block is rendered with its own template and can be customized per theme.
.. code-block:: python
body = StreamField([
("overview", ContentBlock(section="overview")),
("detail", ContentBlock(section="detail")),
])
Content Sections
----------------
**Overview Section**
Displayed on index pages and in feeds. Typically contains a summary or introduction.
**Detail Section**
Additional content shown only on the full post page. Contains the main article body.
Available Blocks
----------------
Heading Block
~~~~~~~~~~~~~
Simple section headings for organizing content.
**Type**: ``heading``
**Usage**:
.. code-block:: python
("heading", blocks.CharBlock(classname="full title"))
**Features**:
- Plain text headings
- Full-width display
- Useful for section breaks
Paragraph Block
~~~~~~~~~~~~~~~
Rich text content with formatting options.
**Type**: ``paragraph``
**Usage**:
.. code-block:: python
("paragraph", blocks.RichTextBlock())
**Features**:
- Bold, italic, links
- Lists (ordered/unordered)
- Standard Wagtail rich text features
- No embedded images (use Image block instead)
Code Block
~~~~~~~~~~
Syntax-highlighted code snippets.
**Type**: ``code``
**Structure**:
.. code-block:: python
class CodeBlock(blocks.StructBlock):
language = blocks.CharBlock()
source = blocks.TextBlock()
**Features**:
- Pygments syntax highlighting
- Support for 100+ programming languages
- Automatic language detection
- Falls back to plain text if language unknown
**Example Usage**:
.. code-block:: json
{
"type": "code",
"value": {
"language": "python",
"source": "def hello():\n print('Hello, World!')"
}
}
Image Block
~~~~~~~~~~~
Responsive images with automatic optimization.
**Type**: ``image``
**Class**: ``CastImageChooserBlock``
**Features**:
- Automatic responsive image generation
- AVIF and JPEG format support
- Multiple renditions for different screen sizes
- Links to full-size image
- Lazy loading support
**Generated Renditions**:
The system automatically creates renditions based on
``CAST_REGULAR_IMAGE_SLOT_DIMENSIONS``.
Each tuple defines a target layout slot, not a single output file. For every
slot, django-cast generates the appropriate rendition widths for multiple pixel
densities and exposes them via ``srcset``:
.. code-block:: python
# Default dimensions
[
(1110, 740),
]
**HTML Output Example**:
.. code-block:: html
Custom block templates are rendered in post detail pages, index/list previews, feeds, API HTML fields, and Wagtail previews through the normal ``{% include_block %}`` path. If a block needs different output in feeds, check the ``render_for_feed`` context value and avoid markup that is unsafe or unhelpful in RSS/Atom descriptions. Media Sync Limits ~~~~~~~~~~~~~~~~~ The first custom-block extension point does not add media extraction hooks. ``Post.sync_media_ids()`` still syncs only django-cast's built-in ``image``, ``gallery``, ``video``, and ``audio`` blocks to the post media relationships. Custom blocks can render chooser values normally, but their media references are not added to ``Post.images``, ``Post.galleries``, ``Post.videos``, or ``Post.audios`` automatically. Media Selection --------------- When editing content, media blocks use Wagtail's chooser interface: 1. **Images**: Filtered by user ownership 2. **Videos**: User's uploaded videos only 3. **Audio**: User's audio files only 4. **Galleries**: Reusable gallery collections This ensures users only see and can select their own media files. Best Practices -------------- Content Structure ~~~~~~~~~~~~~~~~~ 1. Use **overview** for summaries that appear in feeds 2. Place main content in **detail** section 3. Use headings to organize long content 4. Prefer native media blocks over embeds when possible Performance ~~~~~~~~~~~ 1. Avoid too many high-resolution images in one post 2. Use galleries for multiple related images 3. Let the system handle image optimization 4. Don't embed raw HTML with images Accessibility ~~~~~~~~~~~~~ 1. Always provide alt text for images 2. Use semantic headings properly 3. Include transcripts for audio content 4. Ensure embedded content is accessible Migration and Import -------------------- When importing content: .. code-block:: python from wagtail.blocks import StreamValue post.body = StreamValue( post.body.stream_block, [ ("overview", { "heading": "Welcome", "paragraph": "{{ value.quote }}
{% if value.author %} — {{ value.author }} {% endif %}
Introduction text
" }), ("detail", { "paragraph": "Main content
", "image": image.pk, "code": { "language": "python", "source": "print('Hello')" } }) ] ) API Representation ------------------ StreamField content is available via the API as structured JSON: .. code-block:: json { "body": [ { "type": "overview", "value": [ { "type": "heading", "value": "My Post Title" }, { "type": "paragraph", "value": "Summary text...
" } ] } ] } This enables headless CMS usage and content portability.