0
# Content Fields and Blocks
1
2
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.
3
4
## Capabilities
5
6
### Rich Text Field
7
8
Field for rich text content with WYSIWYG editing capabilities, supporting HTML formatting, links, and embedded content.
9
10
```python { .api }
11
class RichTextField(models.TextField):
12
"""
13
Field for rich text content with HTML editing.
14
15
Parameters:
16
editor (str): Editor configuration to use ('default', 'basic', etc.)
17
features (list): List of allowed editor features
18
**kwargs: Standard TextField parameters (max_length, blank, null, etc.)
19
"""
20
def __init__(self, *args, **kwargs):
21
"""Initialize RichTextField with editor configuration."""
22
23
def clone(self):
24
"""Create a copy of this field with the same configuration."""
25
26
def formfield(self, **kwargs):
27
"""Create form field with rich text widget."""
28
29
def get_searchable_content(self, value):
30
"""Extract searchable text content from rich text."""
31
32
def extract_references(self, value):
33
"""Extract references to other objects from rich text."""
34
```
35
36
### Stream Field
37
38
Flexible structured content field that allows mixing different block types in a single field, providing maximum layout flexibility.
39
40
```python { .api }
41
class StreamField(models.Field):
42
"""
43
Field for structured content using blocks.
44
45
Parameters:
46
block_types: List of (name, block) tuples, StreamBlock instance, or block class
47
use_json_field: Ignored, retained for migration compatibility
48
block_lookup: Block definition lookup for migrations
49
min_num (int): Minimum number of blocks required
50
max_num (int): Maximum number of blocks allowed
51
block_counts (dict): Per-block-type count limits
52
collapsed (bool): Whether blocks start collapsed in admin
53
**kwargs: Standard field parameters (blank, null, etc.)
54
"""
55
def __init__(self, block_types, use_json_field=True, block_lookup=None, **kwargs):
56
"""Initialize StreamField with block configuration."""
57
58
@property
59
def stream_block(self):
60
"""Get the StreamBlock instance for this field."""
61
62
@property
63
def json_field(self):
64
"""Get underlying JSONField for storage."""
65
66
def get_internal_type(self):
67
"""Return the internal field type."""
68
69
def to_python(self, value):
70
"""Convert database value to StreamValue."""
71
72
def get_prep_value(self, value):
73
"""Convert StreamValue to database representation."""
74
75
def deconstruct(self):
76
"""Return field constructor arguments for migrations."""
77
```
78
79
### Block System
80
81
Base classes and utilities for creating custom content blocks.
82
83
```python { .api }
84
class Block:
85
"""
86
Base class for content blocks.
87
88
All content blocks inherit from this class.
89
"""
90
def get_form_context(self, value, prefix='', errors=None):
91
"""Get context for rendering the block's form."""
92
93
def render(self, value, context=None):
94
"""Render the block with the given value."""
95
96
def get_api_representation(self, value, context=None):
97
"""Get API representation of block value."""
98
99
class BoundBlock:
100
"""
101
Represents a block instance with a specific value.
102
"""
103
def render(self, context=None):
104
"""Render this block instance."""
105
106
def render_as_block(self, context=None):
107
"""Render with block wrapper."""
108
109
class BlockField(models.Field):
110
"""
111
Form field for block editing in admin interface.
112
"""
113
def __init__(self, block=None, **kwargs):
114
"""Initialize with block definition."""
115
```
116
117
### Field Content Blocks
118
119
Basic content blocks for text, numbers, and simple data input.
120
121
```python { .api }
122
class CharBlock(Block):
123
"""
124
Single line text input block.
125
126
Parameters:
127
required (bool): Whether the field is required
128
max_length (int): Maximum character length
129
min_length (int): Minimum character length
130
help_text (str): Help text for the field
131
validators (list): List of field validators
132
"""
133
def __init__(self, required=True, help_text=None, max_length=None, min_length=None, validators=(), **kwargs):
134
"""Initialize CharBlock with validation options."""
135
136
class TextBlock(Block):
137
"""
138
Multi-line text input block.
139
140
Parameters:
141
required (bool): Whether the field is required
142
rows (int): Number of textarea rows
143
help_text (str): Help text for the field
144
validators (list): List of field validators
145
"""
146
def __init__(self, required=True, help_text=None, rows=1, validators=(), **kwargs):
147
"""Initialize TextBlock with display options."""
148
149
class EmailBlock(Block):
150
"""
151
Email address input with validation.
152
"""
153
def __init__(self, required=True, help_text=None, validators=(), **kwargs):
154
"""Initialize EmailBlock with email validation."""
155
156
class IntegerBlock(Block):
157
"""
158
Integer number input block.
159
160
Parameters:
161
required (bool): Whether the field is required
162
max_value (int): Maximum allowed value
163
min_value (int): Minimum allowed value
164
"""
165
def __init__(self, required=True, help_text=None, max_value=None, min_value=None, validators=(), **kwargs):
166
"""Initialize IntegerBlock with numeric constraints."""
167
168
class FloatBlock(Block):
169
"""
170
Floating point number input block.
171
"""
172
def __init__(self, required=True, help_text=None, max_value=None, min_value=None, validators=(), **kwargs):
173
"""Initialize FloatBlock with numeric constraints."""
174
175
class DecimalBlock(Block):
176
"""
177
Decimal number input with precision control.
178
179
Parameters:
180
max_digits (int): Maximum number of digits
181
decimal_places (int): Number of decimal places
182
"""
183
def __init__(self, required=True, help_text=None, max_digits=None, decimal_places=None, validators=(), **kwargs):
184
"""Initialize DecimalBlock with precision settings."""
185
186
class RegexBlock(Block):
187
"""
188
Text input with regular expression validation.
189
190
Parameters:
191
regex (str): Regular expression pattern
192
error_message (str): Custom error message for validation failure
193
"""
194
def __init__(self, regex, error_message=None, required=True, help_text=None, validators=(), **kwargs):
195
"""Initialize RegexBlock with pattern validation."""
196
197
class URLBlock(Block):
198
"""
199
URL input with validation.
200
"""
201
def __init__(self, required=True, help_text=None, validators=(), **kwargs):
202
"""Initialize URLBlock with URL validation."""
203
204
class BooleanBlock(Block):
205
"""
206
Boolean true/false checkbox block.
207
"""
208
def __init__(self, required=True, help_text=None, **kwargs):
209
"""Initialize BooleanBlock."""
210
211
class DateBlock(Block):
212
"""
213
Date picker block.
214
215
Parameters:
216
format (str): Date format string
217
"""
218
def __init__(self, required=True, help_text=None, format=None, validators=(), **kwargs):
219
"""Initialize DateBlock with date formatting."""
220
221
class TimeBlock(Block):
222
"""
223
Time picker block.
224
225
Parameters:
226
format (str): Time format string
227
"""
228
def __init__(self, required=True, help_text=None, format=None, validators=(), **kwargs):
229
"""Initialize TimeBlock with time formatting."""
230
231
class DateTimeBlock(Block):
232
"""
233
Date and time picker block.
234
235
Parameters:
236
format (str): DateTime format string
237
"""
238
def __init__(self, required=True, help_text=None, format=None, validators=(), **kwargs):
239
"""Initialize DateTimeBlock with datetime formatting."""
240
```
241
242
### Rich Content Blocks
243
244
Advanced blocks for rich content, HTML, and embedded media.
245
246
```python { .api }
247
class RichTextBlock(Block):
248
"""
249
Rich text editor block with formatting capabilities.
250
251
Parameters:
252
editor (str): Editor configuration to use
253
features (list): Allowed editor features
254
"""
255
def __init__(self, editor='default', features=None, **kwargs):
256
"""Initialize RichTextBlock with editor settings."""
257
258
class RawHTMLBlock(Block):
259
"""
260
Raw HTML content block for custom markup.
261
"""
262
def __init__(self, **kwargs):
263
"""Initialize RawHTMLBlock."""
264
265
class BlockQuoteBlock(Block):
266
"""
267
Block quote formatting block.
268
"""
269
def __init__(self, **kwargs):
270
"""Initialize BlockQuoteBlock."""
271
272
class EmbedBlock(Block):
273
"""
274
Embedded content block for videos, social media, etc.
275
"""
276
def __init__(self, **kwargs):
277
"""Initialize EmbedBlock for external content."""
278
```
279
280
### Choice and Selection Blocks
281
282
Blocks for single and multiple selection from predefined options.
283
284
```python { .api }
285
class ChoiceBlock(Block):
286
"""
287
Single selection dropdown block.
288
289
Parameters:
290
choices (list): List of (value, label) tuples
291
"""
292
def __init__(self, choices=(), **kwargs):
293
"""Initialize ChoiceBlock with selection options."""
294
295
class MultipleChoiceBlock(Block):
296
"""
297
Multiple selection checkbox block.
298
299
Parameters:
300
choices (list): List of (value, label) tuples
301
"""
302
def __init__(self, choices=(), **kwargs):
303
"""Initialize MultipleChoiceBlock with selection options."""
304
```
305
306
### Chooser Blocks
307
308
Blocks for selecting related content like pages, images, and documents.
309
310
```python { .api }
311
class PageChooserBlock(Block):
312
"""
313
Page selection block with search interface.
314
315
Parameters:
316
page_type (str): Limit selection to specific page types
317
can_choose_root (bool): Whether root page can be selected
318
"""
319
def __init__(self, page_type=None, can_choose_root=False, **kwargs):
320
"""Initialize PageChooserBlock with type constraints."""
321
322
class DocumentChooserBlock(Block):
323
"""
324
Document selection block.
325
"""
326
def __init__(self, **kwargs):
327
"""Initialize DocumentChooserBlock."""
328
329
class ImageChooserBlock(Block):
330
"""
331
Image selection block.
332
"""
333
def __init__(self, **kwargs):
334
"""Initialize ImageChooserBlock."""
335
336
class SnippetChooserBlock(Block):
337
"""
338
Snippet selection block.
339
340
Parameters:
341
target_model (Model): Snippet model to choose from
342
"""
343
def __init__(self, target_model, **kwargs):
344
"""Initialize SnippetChooserBlock with model constraint."""
345
```
346
347
### Structural Blocks
348
349
Container blocks for organizing and grouping other blocks.
350
351
```python { .api }
352
class StreamBlock(Block):
353
"""
354
Container for multiple different block types in sequence.
355
356
Parameters:
357
local_blocks (list): List of allowed child block types
358
min_num (int): Minimum number of child blocks
359
max_num (int): Maximum number of child blocks
360
block_counts (dict): Per-block-type count limits
361
"""
362
def __init__(self, local_blocks=(), min_num=None, max_num=None, block_counts=None, **kwargs):
363
"""Initialize StreamBlock with child block configuration."""
364
365
class ListBlock(Block):
366
"""
367
Container for repeated instances of a single block type.
368
369
Parameters:
370
child_block (Block): Block type to repeat
371
min_num (int): Minimum number of items
372
max_num (int): Maximum number of items
373
"""
374
def __init__(self, child_block, min_num=None, max_num=None, **kwargs):
375
"""Initialize ListBlock with child block type."""
376
377
class StructBlock(Block):
378
"""
379
Container for a fixed group of named blocks.
380
381
Parameters:
382
local_blocks (list): List of (name, block) tuples defining the structure
383
"""
384
def __init__(self, local_blocks=(), **kwargs):
385
"""Initialize StructBlock with named child blocks."""
386
387
class StaticBlock(Block):
388
"""
389
Placeholder block with no editable content.
390
391
Used for fixed content or separators in StreamField.
392
"""
393
def __init__(self, admin_text=None, template=None, **kwargs):
394
"""Initialize StaticBlock with display text."""
395
```
396
397
### Block Values
398
399
Value containers that hold block content and provide rendering methods.
400
401
```python { .api }
402
class StreamValue:
403
"""
404
Value container for StreamField content.
405
406
Behaves like a list of block instances.
407
"""
408
def __iter__(self):
409
"""Iterate over block instances."""
410
411
def __len__(self):
412
"""Get number of blocks."""
413
414
def __getitem__(self, index):
415
"""Get block at index."""
416
417
def render(self, context=None):
418
"""Render all blocks as HTML."""
419
420
class ListValue:
421
"""
422
Value container for ListBlock content.
423
"""
424
def __iter__(self):
425
"""Iterate over list items."""
426
427
def __len__(self):
428
"""Get number of items."""
429
430
def render(self, context=None):
431
"""Render all items as HTML."""
432
433
class StructValue:
434
"""
435
Value container for StructBlock content.
436
437
Provides attribute-style access to named blocks.
438
"""
439
def __getitem__(self, key):
440
"""Get block value by name."""
441
442
def render(self, context=None):
443
"""Render all blocks as HTML."""
444
```
445
446
## Usage Examples
447
448
### Creating Custom Page with StreamField
449
450
```python
451
from wagtail.models import Page
452
from wagtail.fields import StreamField
453
from wagtail.blocks import CharBlock, TextBlock, RichTextBlock, ImageChooserBlock, StructBlock
454
from wagtail.admin.panels import FieldPanel
455
456
class HomePage(Page):
457
"""Homepage with flexible content blocks."""
458
459
# Define custom blocks
460
class HeroBlock(StructBlock):
461
title = CharBlock(max_length=200)
462
subtitle = TextBlock(max_length=400)
463
background_image = ImageChooserBlock()
464
call_to_action = CharBlock(max_length=100)
465
466
class Meta:
467
template = 'blocks/hero.html'
468
icon = 'image'
469
470
# StreamField with mixed content types
471
content = StreamField([
472
('hero', HeroBlock()),
473
('paragraph', RichTextBlock()),
474
('image', ImageChooserBlock()),
475
('quote', BlockQuoteBlock()),
476
], use_json_field=True)
477
478
content_panels = Page.content_panels + [
479
FieldPanel('content'),
480
]
481
```
482
483
### Advanced Block Configurations
484
485
```python
486
from wagtail.blocks import ListBlock, StructBlock, CharBlock, IntegerBlock, ChoiceBlock
487
488
class TestimonialBlock(StructBlock):
489
"""Structured block for customer testimonials."""
490
quote = TextBlock(max_length=500)
491
author = CharBlock(max_length=100)
492
company = CharBlock(max_length=100, required=False)
493
rating = IntegerBlock(min_value=1, max_value=5)
494
495
class Meta:
496
template = 'blocks/testimonial.html'
497
icon = 'user'
498
499
class FeatureBlock(StructBlock):
500
"""Feature highlight block."""
501
title = CharBlock(max_length=100)
502
description = RichTextBlock(features=['bold', 'italic', 'link'])
503
icon = ChoiceBlock(choices=[
504
('star', 'Star'),
505
('heart', 'Heart'),
506
('check', 'Check'),
507
])
508
509
class Meta:
510
template = 'blocks/feature.html'
511
512
# Using blocks in StreamField
513
content = StreamField([
514
('testimonials', ListBlock(TestimonialBlock())),
515
('features', ListBlock(FeatureBlock(), max_num=6)),
516
], use_json_field=True)
517
```
518
519
### Rich Text Configuration
520
521
```python
522
from wagtail.fields import RichTextField
523
524
class ArticlePage(Page):
525
"""Article page with different rich text configurations."""
526
527
# Full-featured rich text editor
528
body = RichTextField(
529
features=[
530
'h2', 'h3', 'h4', 'bold', 'italic', 'link', 'ol', 'ul',
531
'document-link', 'image', 'embed', 'code', 'superscript', 'subscript'
532
]
533
)
534
535
# Simple rich text for summaries
536
summary = RichTextField(
537
features=['bold', 'italic', 'link'],
538
max_length=500
539
)
540
541
# Basic editor for captions
542
caption = RichTextField(
543
editor='basic',
544
features=['bold', 'italic'],
545
max_length=200
546
)
547
```
548
549
### Custom Block Development
550
551
```python
552
from wagtail.blocks import Block
553
from django import forms
554
555
class ColorBlock(Block):
556
"""Custom block for color picker."""
557
558
def get_form_context(self, value, prefix='', errors=None):
559
context = super().get_form_context(value, prefix, errors)
560
context['widget'] = forms.TextInput(attrs={
561
'type': 'color',
562
'class': 'color-picker'
563
})
564
return context
565
566
def render(self, value, context=None):
567
return f'<div style="background-color: {value}; height: 50px;"></div>'
568
569
class Meta:
570
icon = 'image'
571
template = 'blocks/color.html'
572
573
# Using custom block
574
class DesignPage(Page):
575
color_scheme = StreamField([
576
('color', ColorBlock()),
577
('text', RichTextBlock()),
578
])
579
```