Skip to main content

WhiteNoise

WSGI middleware for easy serving of static files, with optional integration with Django. Secure and efficient enough to use in production.

Just wrap your WSGI application in the WhiteNoise middleware, give it the path to your static files directory and any requests matching files in that directory will be served correctly. All other requests are passed on to your application.

Features

  • Simple to configure

  • Handles caching (sends cache headers and returns Not Modified responses when appropriate)

  • Serves gzipped content (handling Accept-Encoding and Vary headers correctly)

  • Provides hooks for easy customisation, e.g. sending custom headers for certain files

  • Can serve static files from arbitrary URLs, not just from a fixed URL prefix, so you can use it to serve files like /favicon.ico or /robots.txt

  • Python 2/3 compatibile

Shouldn’t I be using a real webserver, or a CDN, or Amazon S3? See Infrequently Asked Questions

QuickStart: Standard WSGI application

from whitenoise import WhiteNoise

from my_project import MyWSGIApp

application = MyWSGIApp()
application = WhiteNoise(application, root='/path/to/static/files')
application.add_files('/path/to/more/static/files', prefix='more-files/')

QuickStart: Django application

In wsgi.py:

from django.core.wsgi import get_wsgi_application
from whitenoise.django import DjangoWhiteNoise

application = get_wsgi_application()
application = DjangoWhiteNoise(application)

This will automatically serve the files in STATIC_ROOT under the prefix derived from STATIC_URL.

If it detects that you are using CachedStaticFilesStorage it will automatically set far-future Expires headers on your static content.

QuickStart: Pre-gzipping content

WhiteNoise comes with a command line utility which will create gzip-compressed versions of files in a directory. WhiteNoise will then serve these compressed files instead, where the client indicates that it accepts them.

$ python -m whitenoise.gzip --help
usage: gzip.py [-h] [-q] [-f] root [extensions [extensions ...]]

Searches for all files inside <root> matching <extensions> and produce gzipped
versions with a '.gz' suffix (as long this results in a smaller file.

positional arguments:
  root         Path root from which to search for files
  extensions   File extensions to match (default: (u'css', u'js'))

optional arguments:
  -h, --help   show this help message and exit
  -q, --quiet  Don't produce log output (default: False)
  -f, --force  Overwrite pre-existing .gz files (default: False)

Infrequently Asked Questions

Shouldn’t I be using a real webserver?

Well, perhaps. Certainly something like nginx will be more efficient at serving static files. But here are a few things to consider:

  1. There are situations (e.g., when hosted on Heroku) where it’s much simpler to have everything handled by your Python application.

  2. WhiteNoise is pretty efficient. Because it only has to serve a fixed set of files it does as much work as it can upfront on initialization, meaning it can serve responses with very little work. Also, when used with gunicorn (and most other WSGI servers) the actual business of pushing the file down the network interface is handled by the kernel’s highly efficient sendfile syscall, not by Python.

  3. If you’re using WhiteNoise behind a CDN or caching proxy (on which more below) then it doesn’t really matter that it’s not as efficient as nginx as the vast majority of static requests will be cached by the CDN and never touch your application.

Shouldn’t I be using a CDN?

Yes, given how cheap and straightforward they are these days, you probably should. But you should be using WhiteNoise to act as the origin, or upstream, server to your CDN.

Under this model, the CDN acts as a caching proxy which sits between your application and the browser (only for static files, you still use your normal domain for dynamic requests). WhiteNoise will send the appropriate cache headers so the CDN can serve requests for static files without hitting your application.

Shouldn’t I be pushing my static files to S3 using something like Django-Storages?

No, you shouldn’t. The problem with this is that Amazon S3 cannot currently selectively serve gzipped content to your users. Gzipping can make dramatic reductions in the bandwidth required for your CSS and JavaScript. But while all browsers in use today can decode gzipped content, your users may be behind crappy corporate proxies or anti-virus scanners which don’t handle gzipped content properly. Amazon S3 forces you to choose whether to serve gzipped content to no-one (wasting bandwidth) or everyone (running the risk of your site breaking for certain users).

The correct behaviour is to examine the Accept-Encoding header of the request to see if gzip is supported, and to return an appropriate Vary header so that intermediate caches know to do the same thing. This is exactly what WhiteNoise does.

Metadata

Release files for whitenoise 0.9

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for whitenoise 0.9
File Size Uploaded
whitenoise-0.9.tar.gz 83.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for whitenoise 0.9
File Interpreter ABI Platform
whitenoise-0.9-py2.py3-none-any.whl Python 3, Python 2 none any Details

Total release size: 94.5 kB

Release files / whitenoise-0.9.tar.gz

Download URL whitenoise-0.9.tar.gz
Size 83.3 kB
Tags Source
SHA-256 checksum
How to use checksums
37c73c4002734a051aff178700e25c5a34693db71009d7d1c15567c2cd2d66e9
BLAKE2b-256 checksum
How to use checksums
6ca2e62e0fd682a4dd28eacbcd1de04cd81c22357857a40ff7437f733bb9f4e2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No

Release files / whitenoise-0.9-py2.py3-none-any.whl

Download URL whitenoise-0.9-py2.py3-none-any.whl
Size 11.2 kB
Tags Python 2 Python 3
SHA-256 checksum
How to use checksums
777ed57537c692d8377e70be24f3a805cf4a7e306ef329ece3ee76e052d3881b
BLAKE2b-256 checksum
How to use checksums
8d97ba7869598f4da6b10670ff047b6799981fb72311a78379d5e46b572bc5cf
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No

Release history Release notifications | RSS feed

6.12.0

2 release files

6.11.0

2 release files

6.9.0

2 release files

6.8.2

2 release files

6.8.1

2 release files

6.8.0

2 release files

6.7.0

2 release files

6.6.0

2 release files

6.5.0

2 release files

6.4.0

2 release files

6.3.0

2 release files

6.2.0

2 release files

6.1.0

2 release files

6.0.0

2 release files

5.3.0

2 release files

5.2.0

2 release files

5.1.0

2 release files

5.0.1

2 release files

5.0

2 release files

4.1.4

2 release files

4.1.3

2 release files

4.1.2

2 release files

4.1.1

2 release files

4.1

2 release files

4.0

2 release files

3.3.1

2 release files

3.3.0

2 release files

3.2.3

2 release files

3.2.2

2 release files

3.2.1

2 release files

3.2

2 release files

3.1

2 release files

3.0

2 release files

2.0.6

2 release files

2.0.5

2 release files

2.0.4

2 release files

2.0.3

2 release files

2.0.2

2 release files

2.0.1

2 release files

2.0

2 release files

1.0.6

2 release files

1.0.5

2 release files

1.0.4

2 release files

1.0.3

2 release files

1.0.2

2 release files

1.0.1

2 release files

1.0

2 release files

0.13

2 release files

0.12

2 release files

0.11

2 release files

0.10

2 release files

This release

0.9 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page