0
# Django Integration
1
2
WhiteNoise provides seamless Django integration through middleware and static file storage classes. These components automatically configure themselves from Django settings and integrate with Django's static file handling system.
3
4
## Capabilities
5
6
### WhiteNoise Middleware
7
8
Django middleware that wraps the core WhiteNoise functionality, automatically configuring itself from Django settings and providing Django-specific optimizations.
9
10
```python { .api }
11
class WhiteNoiseMiddleware(WhiteNoise):
12
"""
13
Django middleware wrapper for WhiteNoise.
14
15
Automatically configures from Django settings and provides Django-specific
16
features like staticfiles integration and development mode detection.
17
"""
18
19
def __init__(self, get_response=None, settings=settings):
20
"""
21
Initialize Django middleware.
22
23
Parameters:
24
- get_response: Django middleware get_response callable
25
- settings: Django settings module (defaults to django.conf.settings)
26
27
Auto-configures from Django settings:
28
- WHITENOISE_AUTOREFRESH (defaults to DEBUG)
29
- WHITENOISE_MAX_AGE (defaults to 0 if DEBUG else 60)
30
- WHITENOISE_ALLOW_ALL_ORIGINS (defaults to True)
31
- WHITENOISE_CHARSET (defaults to 'utf-8')
32
- WHITENOISE_MIMETYPES (defaults to None)
33
- WHITENOISE_ADD_HEADERS_FUNCTION (defaults to None)
34
- WHITENOISE_INDEX_FILE (defaults to None)
35
- WHITENOISE_IMMUTABLE_FILE_TEST (defaults to None)
36
- WHITENOISE_USE_FINDERS (defaults to DEBUG)
37
- WHITENOISE_STATIC_PREFIX (derived from STATIC_URL)
38
- WHITENOISE_ROOT (defaults to None)
39
"""
40
41
def __call__(self, request):
42
"""
43
Django middleware interface.
44
45
Parameters:
46
- request: Django HttpRequest object
47
48
Returns:
49
- Django HttpResponse object or None
50
"""
51
52
@staticmethod
53
def serve(static_file, request):
54
"""
55
Serve static file for Django request (static method).
56
57
Parameters:
58
- static_file: StaticFile instance
59
- request: Django HttpRequest object
60
61
Returns:
62
- WhiteNoiseFileResponse object
63
"""
64
65
def add_files_from_finders(self):
66
"""
67
Add files discovered by Django's staticfiles finders.
68
69
Integrates with Django's STATICFILES_FINDERS to serve files
70
from app directories and other configured locations.
71
"""
72
73
def get_name_without_hash(self, filename):
74
"""
75
Remove version hash from filename.
76
77
Parameters:
78
- filename: File name with potential hash
79
80
Returns:
81
- str: Filename without hash
82
83
Note: Specific to Django's CachedStaticFilesStorage naming scheme.
84
Override for custom versioning systems.
85
"""
86
87
def get_static_url(self, name):
88
"""
89
Get static URL using Django's static file storage.
90
91
Parameters:
92
- name: Static file name
93
94
Returns:
95
- str: Static URL or None if not found
96
"""
97
```
98
99
### WhiteNoise File Response
100
101
Custom Django FileResponse that prevents default header setting to avoid conflicts with WhiteNoise's header management.
102
103
```python { .api }
104
class WhiteNoiseFileResponse(FileResponse):
105
"""
106
Custom FileResponse that prevents default Django header setting.
107
108
Wraps Django's FileResponse to prevent setting default headers that
109
might conflict with WhiteNoise's comprehensive header management.
110
"""
111
112
def set_headers(self, *args, **kwargs):
113
"""Override to prevent automatic header setting."""
114
```
115
116
### Compressed Static Files Storage
117
118
Django static files storage backend that automatically compresses collected files.
119
120
```python { .api }
121
class CompressedStaticFilesStorage(StaticFilesStorage):
122
"""
123
StaticFilesStorage subclass that compresses output files.
124
125
Automatically compresses files during Django's collectstatic process
126
using gzip and optionally Brotli compression.
127
"""
128
129
def post_process(
130
self,
131
paths: dict[str, Any],
132
dry_run: bool = False,
133
**options: Any
134
):
135
"""
136
Compress files after collection.
137
138
Parameters:
139
- paths: Dictionary of collected file paths
140
- dry_run: Skip actual compression if True
141
- options: Additional options
142
143
Yields:
144
- Iterator of (original_name, compressed_name, processed) tuples
145
146
Settings:
147
- WHITENOISE_SKIP_COMPRESS_EXTENSIONS: File extensions to skip
148
"""
149
150
def create_compressor(self, **kwargs):
151
"""
152
Create Compressor instance.
153
154
Parameters:
155
- kwargs: Arguments for Compressor constructor
156
157
Returns:
158
- Compressor: Compression utility instance
159
"""
160
```
161
162
### Compressed Manifest Static Files Storage
163
164
Advanced storage backend that combines Django's manifest static files with compression and optional file cleanup.
165
166
```python { .api }
167
class CompressedManifestStaticFilesStorage(ManifestStaticFilesStorage):
168
"""
169
Extends ManifestStaticFilesStorage with compression and cleanup.
170
171
Combines Django's manifest-based static file versioning with
172
compression and optional removal of non-hashed files.
173
"""
174
175
def __init__(self, *args, **kwargs):
176
"""
177
Initialize with optional manifest strict mode.
178
179
Settings:
180
- WHITENOISE_MANIFEST_STRICT: Override manifest_strict behavior
181
"""
182
183
def post_process(self, *args, **kwargs):
184
"""
185
Process files with hashing and compression.
186
187
Extends parent post_process to add compression of hashed files
188
and optional cleanup of non-hashed originals.
189
190
Settings:
191
- WHITENOISE_KEEP_ONLY_HASHED_FILES: Remove non-hashed files
192
- WHITENOISE_SKIP_COMPRESS_EXTENSIONS: Extensions to skip
193
"""
194
195
def compress_files(self, paths):
196
"""
197
Compress collected and hashed files.
198
199
Parameters:
200
- paths: Iterable of file paths to compress
201
202
Yields:
203
- Iterator of (original_name, compressed_name) tuples
204
"""
205
206
def make_helpful_exception(self, exception, name):
207
"""
208
Create more helpful exception messages for missing file errors.
209
210
Parameters:
211
- exception: Original exception
212
- name: File name causing the error
213
214
Returns:
215
- Exception: Original or enhanced exception
216
"""
217
```
218
219
### Missing File Error
220
221
Exception for static file collection errors with enhanced error messages.
222
223
```python { .api }
224
class MissingFileError(ValueError):
225
"""
226
Exception raised when a referenced static file cannot be found.
227
228
Provides enhanced error messages to help debug missing file references
229
in CSS and other static files.
230
"""
231
```
232
233
## Usage Examples
234
235
### Basic Django Setup
236
237
```python
238
# settings.py
239
MIDDLEWARE = [
240
'whitenoise.middleware.WhiteNoiseMiddleware',
241
'django.middleware.security.SecurityMiddleware',
242
# ... other middleware
243
]
244
245
# Static files configuration
246
STATIC_URL = '/static/'
247
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
248
249
# Optional: Use compression
250
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
251
```
252
253
### Advanced Configuration
254
255
```python
256
# settings.py
257
258
# WhiteNoise specific settings
259
WHITENOISE_USE_FINDERS = True # Enable in development
260
WHITENOISE_AUTOREFRESH = DEBUG # Auto-refresh in debug mode
261
WHITENOISE_MAX_AGE = 31536000 if not DEBUG else 0 # 1 year cache in production
262
263
# Skip compression for these extensions
264
WHITENOISE_SKIP_COMPRESS_EXTENSIONS = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'zip', 'gz', 'tgz', 'bz2', 'tbz', 'xz', 'br']
265
266
# Keep only hashed files (removes originals)
267
WHITENOISE_KEEP_ONLY_HASHED_FILES = True
268
269
# Additional static files root
270
WHITENOISE_ROOT = os.path.join(BASE_DIR, 'public')
271
272
# Custom MIME types
273
WHITENOISE_MIMETYPES = {
274
'.myext': 'application/my-type',
275
}
276
```
277
278
### Custom Header Function
279
280
```python
281
# utils.py
282
def add_custom_headers(headers, path, url):
283
"""Add custom headers to static files."""
284
if url.endswith('.js'):
285
headers['X-Content-Type-Options'] = 'nosniff'
286
headers['Referrer-Policy'] = 'strict-origin-when-cross-origin'
287
288
if url.startswith('/admin/'):
289
headers['X-Frame-Options'] = 'DENY'
290
291
# settings.py
292
WHITENOISE_ADD_HEADERS_FUNCTION = 'myapp.utils.add_custom_headers'
293
```
294
295
### Development Server Integration
296
297
WhiteNoise includes a management command that disables Django's static file serving:
298
299
```python
300
# Add to INSTALLED_APPS
301
INSTALLED_APPS = [
302
# ... other apps
303
'whitenoise.runserver_nostatic',
304
]
305
```
306
307
This automatically enables the `--nostatic` flag for `runserver`, ensuring WhiteNoise handles static files in development.
308
309
### Management Command
310
311
WhiteNoise includes a custom Django management command that disables Django's built-in static file serving.
312
313
```python { .api }
314
class Command(BaseCommand):
315
"""
316
Custom runserver command that disables Django's static file serving.
317
318
Located in whitenoise.runserver_nostatic.management.commands.runserver,
319
this command extends Django's runserver to automatically add the --nostatic
320
flag, ensuring WhiteNoise handles all static file serving.
321
"""
322
323
def add_arguments(self, parser):
324
"""
325
Add command line arguments.
326
327
Extends the base runserver arguments while automatically
328
enabling the --nostatic flag to disable Django's static serving.
329
"""
330
331
def get_handler(self, *args, **options):
332
"""
333
Get WSGI handler with static file serving disabled.
334
335
Returns:
336
- WSGIHandler: Django WSGI handler without static file middleware
337
"""
338
```
339
340
## Django Settings Integration
341
342
WhiteNoise automatically configures itself from Django settings:
343
344
| Setting | Default | Description |
345
|---------|---------|-------------|
346
| `WHITENOISE_AUTOREFRESH` | `DEBUG` | Re-scan files on each request |
347
| `WHITENOISE_MAX_AGE` | `60` (0 if DEBUG) | Cache-Control max-age in seconds |
348
| `WHITENOISE_ALLOW_ALL_ORIGINS` | `True` | Add CORS * header |
349
| `WHITENOISE_CHARSET` | `'utf-8'` | Default charset for text files |
350
| `WHITENOISE_MIMETYPES` | `None` | Additional MIME type mappings |
351
| `WHITENOISE_ADD_HEADERS_FUNCTION` | `None` | Custom header function |
352
| `WHITENOISE_INDEX_FILE` | `None` | Index file name |
353
| `WHITENOISE_IMMUTABLE_FILE_TEST` | `None` | Immutable file test |
354
| `WHITENOISE_USE_FINDERS` | `DEBUG` | Use Django staticfiles finders |
355
| `WHITENOISE_STATIC_PREFIX` | Derived from `STATIC_URL` | Static files URL prefix |
356
| `WHITENOISE_ROOT` | `None` | Additional static files directory |
357
| `WHITENOISE_SKIP_COMPRESS_EXTENSIONS` | Built-in list | Extensions to skip compression |
358
| `WHITENOISE_KEEP_ONLY_HASHED_FILES` | `False` | Remove non-hashed files |
359
| `WHITENOISE_MANIFEST_STRICT` | `None` | Override manifest strict mode |
360
361
## Types
362
363
```python { .api }
364
from typing import Any, Iterator, Union
365
from django.http import HttpRequest, HttpResponse
366
from django.contrib.staticfiles.storage import StaticFilesStorage, ManifestStaticFilesStorage
367
368
# Django middleware get_response type
369
GetResponseCallable = Callable[[HttpRequest], HttpResponse]
370
371
# Post-process iterator type
372
PostProcessIterator = Iterator[Union[tuple[str, str, bool], tuple[str, None, RuntimeError]]]
373
```