0
# Django Sekizai
1
2
Django Sekizai provides a template-based block system for managing CSS and JavaScript resources in Django applications. It enables developers to define placeholders where blocks get rendered and allows sub-templates to append content to those blocks from different places in the template hierarchy, with automatic deduplication of content.
3
4
## Package Information
5
6
- **Package Name**: django-sekizai
7
- **Language**: Python
8
- **Installation**: `pip install django-sekizai`
9
- **Django Integration**: Add `'sekizai'` to `INSTALLED_APPS`
10
11
## Core Imports
12
13
```python
14
# Context processor
15
from sekizai.context_processors import sekizai
16
17
# Context class for when no request is available
18
from sekizai.context import SekizaiContext
19
20
# Helper functions
21
from sekizai.helpers import validate_template, get_namespaces, Watcher, get_varname, get_context
22
23
# Template tag functions (advanced usage)
24
from sekizai.templatetags.sekizai_tags import validate_context, import_processor
25
26
# Data structures
27
from sekizai.data import UniqueSequence
28
```
29
30
Template usage:
31
```django
32
{% load sekizai_tags %}
33
```
34
35
## Basic Usage
36
37
### 1. Configure Django Settings
38
39
```python
40
# settings.py
41
INSTALLED_APPS = [
42
# ... other apps
43
'sekizai',
44
]
45
46
TEMPLATES = [
47
{
48
'BACKEND': 'django.template.backends.django.DjangoTemplates',
49
'OPTIONS': {
50
'context_processors': [
51
# ... other processors
52
'sekizai.context_processors.sekizai',
53
],
54
},
55
},
56
]
57
```
58
59
### 2. Define Blocks in Base Template
60
61
```django
62
<!-- base.html -->
63
<!DOCTYPE html>
64
<html>
65
<head>
66
{% load sekizai_tags %}
67
{% render_block "css" %}{% endrender_block %}
68
</head>
69
<body>
70
{% block content %}{% endblock %}
71
{% render_block "js" %}{% endrender_block %}
72
</body>
73
</html>
74
```
75
76
### 3. Add Content to Blocks from Sub-Templates
77
78
```django
79
<!-- some_template.html -->
80
{% extends "base.html" %}
81
{% load sekizai_tags %}
82
83
{% addtoblock "css" %}
84
<link rel="stylesheet" href="/static/css/special.css">
85
{% endaddtoblock %}
86
87
{% addtoblock "js" %}
88
<script src="/static/js/special.js"></script>
89
{% endaddtoblock %}
90
91
{% block content %}
92
<h1>My Page</h1>
93
{% endblock %}
94
```
95
96
## Capabilities
97
98
### Template Tags
99
100
Template tags for managing blocks in Django templates.
101
102
```python { .api }
103
# render_block - Render accumulated block content with optional postprocessor
104
{% render_block "block_name" %}
105
<!-- Optional content that gets rendered after sekizai data -->
106
{% endrender_block %}
107
108
# With postprocessor function
109
{% render_block "block_name" postprocessor "module.path.to.function" %}
110
<!-- Optional content that gets rendered after sekizai data -->
111
{% endrender_block %}
112
113
# addtoblock - Add content to a block with optional preprocessing
114
{% addtoblock "block_name" %}
115
<!-- Content to add to the block -->
116
{% endaddtoblock %}
117
118
# With strip flag to remove leading/trailing whitespace
119
{% addtoblock "block_name" strip %}
120
<!-- Content to add (whitespace will be stripped) -->
121
{% endaddtoblock %}
122
123
# With preprocessor function
124
{% addtoblock "block_name" preprocessor "module.path.to.function" %}
125
<!-- Content to add (will be processed by function) -->
126
{% endaddtoblock %}
127
128
# With both strip and preprocessor
129
{% addtoblock "block_name" strip preprocessor "module.path.to.function" %}
130
<!-- Content to add (stripped then processed) -->
131
{% endaddtoblock %}
132
133
# add_data - Add string data directly to a block
134
{% add_data "block_name" "content_string" %}
135
136
# with_data - Access block content as template variable
137
{% with_data "block_name" as variable_name %}
138
<!-- variable_name contains list of block content strings -->
139
{% end_with_data %}
140
```
141
142
### Context Processor
143
144
Context processor for making sekizai functionality available in templates.
145
146
```python { .api }
147
def sekizai(request=None):
148
"""
149
Context processor that makes SekizaiDictionary available in templates.
150
151
Parameters:
152
- request: HttpRequest or None, optional HTTP request object
153
154
Returns:
155
Dict[str, UniqueSequence]: Context dictionary with sekizai data structure
156
"""
157
```
158
159
### Context Class
160
161
Alternative context class for use when no request is available.
162
163
```python { .api }
164
class SekizaiContext(Context):
165
"""
166
Context class that includes sekizai functionality without requiring a request.
167
168
Inherits from django.template.Context and automatically includes sekizai data.
169
"""
170
171
def __init__(self, *args, **kwargs):
172
"""
173
Initialize context with sekizai data.
174
175
Parameters:
176
- *args: Positional arguments passed to parent Context
177
- **kwargs: Keyword arguments passed to parent Context
178
"""
179
```
180
181
### Template Validation
182
183
Functions for validating templates contain required sekizai blocks.
184
185
```python { .api }
186
def validate_template(template, namespaces):
187
"""
188
Validate that a template contains all required namespaces.
189
190
Parameters:
191
- template (str): Template name or path
192
- namespaces (list): List of namespace names to validate
193
194
Returns:
195
bool: True if template is valid, False otherwise
196
197
Note: Validation can be disabled with SEKIZAI_IGNORE_VALIDATION = True
198
"""
199
200
def get_namespaces(template):
201
"""
202
Get all sekizai namespaces found in a template and its inheritance chain.
203
204
Parameters:
205
- template (str): Template name or path
206
207
Returns:
208
list: List of namespace strings found in template
209
"""
210
```
211
212
### Configuration Helpers
213
214
Helper functions for sekizai configuration and settings.
215
216
```python { .api }
217
def get_varname():
218
"""
219
Get the context variable name used for sekizai data.
220
221
Returns:
222
str: Variable name (default: 'SEKIZAI_CONTENT_HOLDER' or SEKIZAI_VARNAME setting)
223
"""
224
225
def get_context():
226
"""
227
Create a basic Django template context with empty template.
228
229
Returns:
230
Context: Django template context with empty template attached
231
"""
232
```
233
234
### Context Validation
235
236
Functions for validating template contexts contain sekizai data.
237
238
```python { .api }
239
def validate_context(context):
240
"""
241
Validate that a template context contains sekizai data.
242
243
Parameters:
244
- context: Django template context
245
246
Returns:
247
bool: True if context is valid, False if invalid but should be ignored
248
249
Raises:
250
TemplateSyntaxError: If context is invalid and template engine is in debug mode
251
"""
252
```
253
254
### Data Structures
255
256
Core data structures used by sekizai.
257
258
```python { .api }
259
class UniqueSequence(MutableSequence):
260
"""
261
Sequence container that automatically prevents duplicate entries.
262
263
Implements collections.abc.MutableSequence interface with automatic deduplication.
264
"""
265
266
def __init__(self):
267
"""Initialize empty sequence."""
268
269
def __contains__(self, item):
270
"""Check if item exists in sequence."""
271
272
def __iter__(self):
273
"""Iterate over sequence items."""
274
275
def __getitem__(self, item):
276
"""Get item by index."""
277
278
def __setitem__(self, key, value):
279
"""Set item at index."""
280
281
def __delitem__(self, key):
282
"""Delete item at index."""
283
284
def __len__(self):
285
"""Get sequence length."""
286
287
def insert(self, index, value):
288
"""
289
Insert value at index if not already present.
290
291
Parameters:
292
- index (int): Position to insert at
293
- value: Value to insert (ignored if already exists)
294
"""
295
```
296
297
### Change Monitoring
298
299
Classes for monitoring sekizai data changes, useful for caching scenarios.
300
301
```python { .api }
302
class Watcher:
303
"""
304
Monitor context for changes to sekizai data for caching purposes.
305
306
Note: Assumes you ONLY ADD, NEVER REMOVE data from context.
307
"""
308
309
def __init__(self, context):
310
"""
311
Initialize watcher with template context.
312
313
Parameters:
314
- context: Django template context to monitor
315
"""
316
317
@property
318
def data(self):
319
"""
320
Get current sekizai data from context.
321
322
Returns:
323
dict: Current sekizai data
324
"""
325
326
def get_changes(self):
327
"""
328
Get changes to sekizai data since watcher initialization.
329
330
Returns:
331
dict: Dictionary of changes with new and modified data
332
"""
333
```
334
335
### Processor Functions
336
337
Functions for handling pre and post processing of block content.
338
339
```python { .api }
340
def import_processor(import_path):
341
"""
342
Import and return a processor function by dotted path.
343
344
Parameters:
345
- import_path (str): Dotted import path to processor function
346
347
Returns:
348
callable: Imported processor function
349
350
Raises:
351
TypeError: If import path doesn't contain at least one dot
352
"""
353
```
354
355
## Settings Configuration
356
357
### Required Settings
358
359
```python
360
# settings.py
361
362
# Add to INSTALLED_APPS
363
INSTALLED_APPS = [
364
'sekizai',
365
# ... other apps
366
]
367
368
# Add context processor
369
TEMPLATES = [
370
{
371
'BACKEND': 'django.template.backends.django.DjangoTemplates',
372
'OPTIONS': {
373
'context_processors': [
374
'sekizai.context_processors.sekizai',
375
# ... other processors
376
],
377
},
378
},
379
]
380
```
381
382
### Optional Settings
383
384
```python
385
# Optional: Custom variable name for sekizai data (default: 'SEKIZAI_CONTENT_HOLDER')
386
SEKIZAI_VARNAME = 'MY_SEKIZAI_DATA'
387
388
# Optional: Disable template validation (default: False)
389
SEKIZAI_IGNORE_VALIDATION = True
390
```
391
392
## Common Usage Patterns
393
394
### CSS and JavaScript Management
395
396
The most common use case is managing CSS and JavaScript resources:
397
398
```django
399
<!-- base.html -->
400
<!DOCTYPE html>
401
<html>
402
<head>
403
{% load sekizai_tags %}
404
<title>My Site</title>
405
{% render_block "css" %}
406
</head>
407
<body>
408
{% block content %}{% endblock %}
409
{% render_block "js" %}{% endrender_block %}
410
</body>
411
</html>
412
```
413
414
```django
415
<!-- page_template.html -->
416
{% extends "base.html" %}
417
{% load sekizai_tags %}
418
419
{% addtoblock "css" %}
420
<link rel="stylesheet" href="{% static 'css/page-specific.css' %}">
421
{% endaddtoblock %}
422
423
{% addtoblock "js" %}
424
<script src="{% static 'js/page-specific.js' %}"></script>
425
{% endaddtoblock %}
426
427
{% block content %}
428
<h1>My Page</h1>
429
{% endblock %}
430
```
431
432
### Using Without Request Context
433
434
```python
435
from sekizai.context import SekizaiContext
436
from django.template import Template
437
438
# Create context without request
439
context = SekizaiContext({'variable': 'value'})
440
441
# Render template
442
template = Template("{% load sekizai_tags %}{% addtoblock 'css' %}...")
443
result = template.render(context)
444
```
445
446
### Template Validation
447
448
```python
449
from sekizai.helpers import validate_template, get_namespaces
450
451
# Check if template has required blocks
452
is_valid = validate_template('my_template.html', ['css', 'js'])
453
454
# Get all blocks used in template
455
namespaces = get_namespaces('my_template.html')
456
print(namespaces) # ['css', 'js', 'meta']
457
```
458
459
### Monitoring Changes for Caching
460
461
```python
462
from sekizai.helpers import Watcher
463
464
# Monitor context changes
465
watcher = Watcher(context)
466
467
# ... template rendering that modifies sekizai blocks ...
468
469
# Get what changed
470
changes = watcher.get_changes()
471
# Use changes for cache invalidation
472
```
473
474
## Error Handling
475
476
### Common Errors
477
478
**TemplateSyntaxError**: Raised when sekizai context processor is not enabled and template engine is in debug mode.
479
480
```python
481
# Solution: Add context processor to settings
482
TEMPLATES = [
483
{
484
'OPTIONS': {
485
'context_processors': [
486
'sekizai.context_processors.sekizai',
487
],
488
},
489
},
490
]
491
```
492
493
**TypeError**: Raised by `import_processor` when import path doesn't contain dots.
494
495
```python
496
# Incorrect
497
import_processor('myfunction') # TypeError
498
499
# Correct
500
import_processor('mymodule.myfunction')
501
```