Overly simplified: You need something that executes Python but Python isn't the best at handling all types of requests.
[disclaimer: I'm a Gunicorn developer]
Less simplified: Regardless of what app server you use (Gunicorn, mod_wsgi, mod_uwsgi, cherrypy) any sort of non-trivial deployment will have something upstream that will handle the requests that your Django app should not be handling. Trivial examples of such requests are serving static assets (images/css/js).
This results in two first tiers of the classic "three tier architecture". Ie, the webserver (Nginx in your case) will handle many requests for images and static resources. Requests that need to be dynamically generated will then be passed on to the application server (Gunicorn in your example). (As an aside, the third of the three tiers is the database)
Historically speaking, each of these tiers would be hosted on separate machines (and there would most likely be multiple machines in the first two tiers, ie: 5 web servers dispatch requests to two app servers which in turn query a single database).
In the modern era we now have applications of all shapes and sizes. Not every weekend project or small business site actually needs the horsepower of multiple machines and will run quite happily on a single box. This has spawned new entries into the array of hosting solutions. Some solutions will marry the app server to the web server (Apache httpd + mod_wsgi, Nginx + mod_uwsgi, etc). And its not at all uncommon to host the database on the same machine as one of these web/app server combinations.
Now in the case of Gunicorn, we made a specific decision (copying from Ruby's Unicorn) to keep things separate from Nginx while relying on Nginx's proxying behavior. Specifically, if we can assume that Gunicorn will never read connections directly from the internet, then we don't have to worry about clients that are slow. This means that the processing model for Gunicorn is embarrassingly simple.
The separation also allows Gunicorn to be written in pure Python which minimizes the cost of development while not significantly impacting performance. It also allows users the ability to use other proxies (assuming they buffer correctly).
As to your second question about what actually handles the HTTP request, the simple answer is Gunicorn. The complete answer is both Nginx and Gunicorn handle the request. Basically, Nginx will receive the request and if it's a dynamic request (generally based on URL patterns) then it will give that request to Gunicorn, which will process it, and then return a response to Nginx which then forwards the response back to the original client.
So in closing, yes. You need both Nginx and Gunicorn (or something similar) for a proper Django deployment. If you're specifically looking to host Django with Nginx, then I would investigate Gunicorn, mod_uwsgi, and maybe CherryPy as candidates for the Django side of things.
I had the same issue with genericpath.py giving a UnicodeEncodeError when attempting to upload a file name with non ASCII characters.
I was using nginx, uwsgi and django with python 2.7.
Everything was working OK locally but not on the server
Here are the steps I took
1. added to /etc/nginx/nginx.conf (did not fix the problem)
http {
charset utf-8;
}
- I added this line to etc/default/locale (did not fix the problem)
LANGUAGE="en_US.UTF-8"
I followed the instructions here listed under the heading 'Success'
https://code.djangoproject.com/wiki/ExpectedTestFailures (did not fix the problem)
aptitude install language-pack-en-base
Found across this ticket
https://code.djangoproject.com/ticket/17816
which suggested testing a view on the server to what was happening with locale information
In your view
import locale
locales = "Current locale: %s %s -- Default locale: %s %s" % (locale.getlocale() + locale.getdefaultlocale())
In your template
{{ locales }}
For me, the issue was that I had no locale and no default locale on my Ubuntu server (though I did have them on my local OSX dev machine) then files with non ASCII file names/paths will not upload correctly with python raising a UnicodeEncodeError, but only on the production server.
Solution
I added this to both my site and my site admin uwsgi config files
e.g. /etc/uwsgi-emperor/vassals/my-site-config-ini file
env = LANG=en_US.utf8
Best Answer
As mentioned in the comments by Tero Kilkanen, it turns out that the problem was the code itself.
I was hammering the server with requests in order to achieve some semblance of a realtime application and this in turn made the entire server unavailable to serve other requests.
Looking at the server stats did not help elucidate the problem since all metrics showed the server to be available for work.
So if you encounter such a problem, look at your Nginx logs for multiple requests within a short interval.