Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.2k views
in Technique[技术] by (71.8m points)

nginx - Host Django on subfolder

I have deployed Django with Gunicorn and NGINX, and it works fine, if the Django app is served on the root url, with this configuration:

server {
    listen 80;

    location = /favicon.ico { access_log off; log_not_found off; }

    location / {
        include proxy_params;
        proxy_pass http://unix:my_app.sock;
    }
}

However when I try to serve the Django app on another URL, it doesn't work. If I try to access http://domain/my_app/admin/ then Django tells me it cannot find the view.

This is the NGINX config:

server {
    listen 80;

    location = /favicon.ico { access_log off; log_not_found off; }

    location /my_app {
        include proxy_params;
        proxy_pass http://unix:/var/my_app/app.sock;
    }
}

How could I make this work? I was not able to find any solution to specify something like a "BASE_URL" so far.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

My comment doesn't show the whole picture. When I've run Django sites on subfolders, I like to use a dynamic config so that you can still access the machine directly (without the proxy) and have a working web-app. This can help a LOT for debugging tricky stuff like this that is hard to reproduce in dev.

If you do not have the ability to pass the header or modify wsgi.py, you can still set FORCE_SCRIPT_NAME in your Django settings.

3 steps:

  1. set up a proxy in front of the webserver that strips the subfolder out of the URL
  2. set the X-Script-Name header so that your Django site generates its urls with /myapp/ infront of them -- make sure you're using the {% url %} tag and reverse, vs. hard-coding!
  3. modify myapp/wsgi.py to read a new header X-Script-Name into the wsgi environment variable SCRIPT_NAME (based on this flask snippet)

Here is an example Nginx config for a proxy that points to a Django site on a subdirectory and also sets X-Script-Name (steps 1 and 2), note that this doesn't use a unix socket, so it's a little different from the OP's question. Would welcome an edit:

nginx.conf

location /my_app {
    proxy_pass https://mywebapp.com/;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Script-Name /my_app;
    proxy_cookie_path / /my_app;
}

And to read X-Script-Name:

myapp/wsgi.py

import os

from django.core.wsgi import get_wsgi_application

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "myapp.settings")

_application = get_wsgi_application()


def application(environ, start_response):
    # http://flask.pocoo.org/snippets/35/
    script_name = environ.get('HTTP_X_SCRIPT_NAME', '')
    if script_name:
        environ['SCRIPT_NAME'] = script_name
        path_info = environ['PATH_INFO']
        if path_info.startswith(script_name):
            environ['PATH_INFO'] = path_info[len(script_name):]

    scheme = environ.get('HTTP_X_SCHEME', '')
    if scheme:
        environ['wsgi.url_scheme'] = scheme

    return _application(environ, start_response)

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...