Mind that age! This blog post is 10 years old! Most likely, its content is outdated. Especially if it's technical.

When doing local Django development with runserver you end up doing some changes, then refreshing in Firefox/Chrome/Safari again and again. Doing this means that all your static resources are probably served via Django. Presumably via django.views.static.serve , right? What's wrong with that? Not much, but we can do better.

So, you serve it via Nginx and let Nginx take care of all static resources. You'll still use Django's own runserver so no need for mod_wsgi , gunicorn or uWSGI . This requires that you have Nginx installed and running on your local development environment. First you need to decide on a fake domain name. For example mylittlepony . Edit your /etc/hosts file by adding this line:

127.0.1.1 mylittlepony

Then create the file /etc/nginx/sites-available/mylittlepony and type something like this in it:

server { root /home/peterbe/projects/mylittlepony/static; server_name mylittlepony; gzip off; location = /favicon.ico { rewrite "/favicon.ico" /img/favicon.ico; } proxy_set_header Host $host; location / { if (-f $request_filename) { add_header X-Static hit; access_log off; } if (!-f $request_filename) { proxy_pass http://127.0.0.1:8000; add_header X-Static miss; } } }

Then when you've done that enable it:

# cd /etc/nginx/sites-enabled # ln -s ../sites-available/mylittlepony # /etc/init.d/nginx reload

Now test the site with curl or something:

$ curl -I http://mylittlepony/ HTTP/1.1 200 OK Server: nginx/0.7.65 Date: Fri, 08 Oct 2010 14:35:04 GMT Content-Type: text/html; charset=utf-8 Connection: keep-alive Expires: Fri, 08 Oct 2010 14:35:04 GMT Vary: Cookie Last-Modified: Fri, 08 Oct 2010 14:35:04 GMT ETag: "fecf14808e52fe8652373f6e49e1ac06" Cache-Control: max-age=0 Set-Cookie: csrftoken=f6eb9e767ca058ecde24bb51c8db9448; Max-Age=31449600; Path=/ Set-Cookie: sessionid=c48af92360ad29410d199081e6067f54; expires=Fri, 22-Oct-2010 14:35:04 GMT; Max-Age=1209600; Path=/ X-Static: miss

Now test to get a static resource:

$ curl -I http://mylittlepony/css/jquery-ui-1.8.4.css HTTP/1.1 200 OK Server: nginx/0.7.65 Date: Fri, 08 Oct 2010 14:36:31 GMT Content-Type: text/css Content-Length: 24806 Last-Modified: Tue, 31 Aug 2010 18:11:38 GMT Connection: keep-alive X-Static: hit Accept-Ranges: bytes

Awesome! If you're curious how much faster Nginx is than Django's serve view, here's a hasty benchmark from my laptop:

# ab -n 10000 -c 10 http://localhost:8000/css/jquery-ui-1.8.4.css ... Requests per second: 446.34 [#/sec] (mean) Time per request: 22.405 [ms] (mean) Time per request: 2.240 [ms] (mean, across all concurrent requests) Transfer rate: 10893.44 [Kbytes/sec] received ...

And the same directly from Nginx:

# ab -n 10000 -c 10 http://mylittlepony/css/jquery-ui-1.8.4.css ... Requests per second: 15709.54 [#/sec] (mean) Time per request: 0.637 [ms] (mean) Time per request: 0.064 [ms] (mean, across all concurrent requests) Transfer rate: 384039.88 [Kbytes/sec] received

Obviously you're not going to be able to hit your website that hard but trust me, when you work like this a lot and do a lot of refreshing over and over (working on some Javascript code for example) you can really feel the difference. The static resources load faster because and Django just have to do one single thing which is to create the HTML page. Your stdout on the runserver is only going to log actual views used. Like this:

[08/Oct/2010 15:43:14] "GET / HTTP/1.0" 200 8639 [08/Oct/2010 15:43:27] "GET /crm/clients/ HTTP/1.0" 200 28830 [08/Oct/2010 15:43:30] "GET /crm/clients/A1215/ HTTP/1.0" 200 12804

I hope this helps other people shave milliseconds off their development time.

Related posts