Trop simplifié: Vous avez besoin de quelque chose qui exécute Python, mais Python n'est pas le meilleur pour traiter tous les types de demandes.
[disclaimer: je suis un développeur de Gunicorn]
Moins simplifié: quel que soit le serveur d'application utilisé (Gunicorn, mod_wsgi, mod_uwsgi, cherrypy), tout type de déploiement non trivial aura quelque chose en amont qui gérera les demandes que votre application Django ne devrait pas traiter. Des exemples triviaux de telles demandes servent des actifs statiques (images / css / js).
Il en résulte deux premiers niveaux de la "architecture à trois niveaux" classique. En d'autres termes, le serveur Web (Nginx dans votre cas) traitera de nombreuses demandes d'images et de ressources statiques. Les demandes devant être générées dynamiquement seront ensuite transmises au serveur d'applications (Gunicorn dans votre exemple). (En passant, le troisième des trois niveaux est la base de données)
Historiquement, chacun de ces niveaux était hébergé sur des machines distinctes (et il y aurait probablement plusieurs machines dans les deux premiers niveaux, c.-à-d.: 5 serveurs Web envoient des demandes à deux serveurs d'applications, qui interrogent à leur tour une seule base de données).
À l'ère moderne, nous avons maintenant des applications de toutes formes et de toutes tailles. Ce ne sont pas tous les projets de week-end ou les sites de petites entreprises qui ont réellement besoin de la puissance de plusieurs machines et qui fonctionnent sans problème sur une seule boîte. Cela a engendré de nouvelles entrées dans la gamme de solutions d'hébergement. Certaines solutions vont associer le serveur d'applications au serveur Web (Apache httpd + mod_wsgi, Nginx + mod_uwsgi, etc.). Et il n’est pas du tout inhabituel d’héberger la base de données sur le même ordinateur que l’une de ces combinaisons serveur Web / application.
Maintenant, dans le cas de Gunicorn, nous avons pris une décision spécifique (copie de la Licorne de Ruby) de séparer les éléments de Nginx tout en nous appuyant sur le comportement de proxy de Nginx. Plus précisément, si nous pouvons supposer que Gunicorn ne lira jamais les connexions directement à partir d’Internet, nous n’avons pas à nous inquiéter des clients lents. Cela signifie que le modèle de traitement pour Gunicorn est d'une simplicité embarrassante.
La séparation permet également à Gunicorn d’être écrit en Python pur, ce qui minimise les coûts de développement sans affecter de manière significative les performances. Cela permet également aux utilisateurs d’utiliser d’autres proxies (en supposant qu’ils tamponnent correctement).
En ce qui concerne votre deuxième question sur ce qui gère réellement la requête HTTP, la réponse simple est Gunicorn. La réponse complète est que Nginx et Gunicorn gèrent la demande. Fondamentalement, Nginx recevra la demande. S'il s'agit d'une demande dynamique (généralement basée sur des modèles d'URL), elle donnera cette demande à Gunicorn, qui la traitera, puis renverra une réponse à Nginx qui la renverra ensuite à l'original. client.
Donc en terminant, oui. Vous avez besoin à la fois de Nginx et de Gunicorn (ou quelque chose de similaire) pour un déploiement correct de Django. Si vous cherchez spécifiquement à héberger Django avec Nginx, alors je me renseignerais sur Gunicorn, mod_uwsgi et peut-être CherryPy en tant que candidats pour le côté Django.