aaron maxwell

Django and Lighttpd: one niggling fastCGI detail

If you are setting up a Django website using the lighttpd web server, one of the easiest ways to configure it is via fastcgi, which lighttpd has built-in support for. As I write this, the official Django FastCGI docs do a very good job of explaining everything, provided you read the whole document. (Don't just skip to the lighttpd section - relevant info is contained earlier, perhaps even in the Apache sections.)

The docs skimp over one detail that happened to affect me, however, which I'd like to document here in hopes that it will save you some time: the FORCE_SCRIPT_NAME setting. At first, when I called up the admin site and clicked the submit button to log in, I got a 404 error, for a url like "/mysite.fcgi/admin/". mysite.fcgi (not its real name :) is the url prefix I configured for the fastcgi rewrite rule in the lighttpd configuration.

After much research and fruitless tweaking of the config files, I thought to look at the HTML source of the admin login page (which served just fine). Turns out the action attribute of the login form element was set to "/mysite.fcgi/admin/", not "/admin/" or ".", like it should be. At the tail end of the above docs, I got a clue as to the cause. Long story short, defining FORCE_SCRIPT_NAME to the empty string in settings.py solved the problem.

There... hope this saves someone an hour or two!

Comments:

Ben said...

Thanks :D It saved me an hour or two.

tulcod said...

sheesh, this could've saved me three hours. at least it probably saved me another three, so i guess i'm obligated to say "thanks" now :)

Ryan said...

Wow. I searched for two days to figure this out. Thanks for posting it. You probably saved me another day.

Javier Camuñas said...

thanks, i was frikin out!

Jean-Henri said...

Thank you very much, you just saved my evening ! Thank you so much.

Daniel said...

I just did my first ever Django + Lighttpd install today, and encountered this strangeness. Despite the Django docs saying that it tries to figure out the URL prefix to strip based on the SCRIPT_NAME it sees, this doesn't seem to work.

What I did find however, is that I could get by with a very much simplified setup (and didn't need to set FORCE_SCRIPT_NAME):

fastcgi.server = (
"/" => (
"main" => (
"socket" => "/tmp/myapp.sock",
"check-local" => "disable",
"fix-root-scriptname" => "enable",
)
),
)
alias.url = (
"/media" => "/opt/myapp/media/",
"/admin/media" => "/opt/django-src/django/contrib/admin/media/",
)

url.rewrite-once = (
"^(/media/.*)$" => "$1",
"^(/admin/media/.*)$" => "$1",
"^/favicon\.ico$" => "/media/favicon.ico",
)

Using the "fix-root-scriptname" config option in Lighttpd, I was then able to drop the rewrite rules for "^(/.*)$".

Obviously this assumes that:
a) you have all your media under one directory
b) you do not have multiple FastCGI backends that you want to use