or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

admin-interface.mdapi.mdcontent-fields.mdcontrib.mdindex.mdmedia.mdpage-models.mdsearch.mdsystem-integration.mdtemplates.mdworkflows.md

content-fields.mddocs/

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

```