nginx 在子文件夹上托管Django

iqjalb3h  于 2023-01-01  发布在  Nginx
关注(0)|答案(3)|浏览(171)

我已经在Gunicorn和NGINX上部署了Django,如果Django应用程序在根URL上提供服务,使用以下配置,它可以正常工作:

server {
    listen 80;

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

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

但是当我尝试在另一个URL上提供Django应用时,它不工作。如果我尝试访问http://domain/my_app/admin/,Django告诉我它找不到视图。
这是NGINX配置:

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;
    }
}

我怎样才能做到这一点呢?到目前为止,我还没有找到任何解决方案来指定像“BASE_URL”这样的东西。

wrrgggsh

wrrgggsh1#

我的评论并没有显示全貌。当我在子文件夹上运行Django站点时,我喜欢使用动态配置,这样你仍然可以直接访问机器(没有代理)并拥有一个工作的Web应用程序。这对调试像这样在开发中很难重现的棘手问题有很大帮助。
如果您无法传递头文件或修改wsgi.py,您仍然可以在Django设置中设置FORCE_SCRIPT_NAME
3个步骤:
1.在Web服务器前面设置代理,从URL中删除子文件夹
1.设置X-Script-Name头文件,使Django站点生成的url前面带有/myapp/--确保使用的是{% url %}标签和reverse,而不是硬编码!
1.修改myapp/wsgi.py,将新的头文件X-Script-Name读入wsgi环境变量SCRIPT_NAME(基于this flask snippet
下面是一个代理的Nginx配置示例,它指向子目录上的Django站点,并设置了X-Script-Name(步骤1和2),注意这没有使用unix套接字,所以它与OP的问题有点不同。欢迎编辑:
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;
}

要读取X-Script-Name:
我的应用程序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)
c86crjj0

c86crjj02#

这是我解决这个问题的方法。我可以在同一个服务器/域上运行多个django。

项目/settings.py

MY_PROJECT = env('MY_PROJECT', '')  # example; '/dj'
if MY_PROJECT:
    USE_X_FORWARDED_HOST = True
    FORCE_SCRIPT_NAME = MY_PROJECT + "/"
    SESSION_COOKIE_PATH = MY_PROJECT + "/"

LOGIN_URL = "login/"
LOGIN_REDIRECT_URL = MY_PROJECT + "/"
LOGOUT_REDIRECT_URL = MY_PROJECT + "/"

NGINX配置

location /dj/ {
    proxy_set_header X-Forwarded-Protocol $scheme;
    proxy_set_header Host $http_host;
    proxy_set_header X-Scheme $scheme;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    proxy_pass http://127.0.0.1:8000/;
}

请注意,位置url应以“/”结尾

myzjeezk

myzjeezk3#

@andyC感谢您的解答。
在最新的Django(4.1.4)中,它使用了以下设置。我在nginx中为Django做了以下设置,它位于API网关之后。
settings.py

USE_X_FORWARDED_HOST = True
FORCE_SCRIPT_NAME = '/content/'
SESSION_COOKIE_PATH = '/content/'

LOGIN_URL = "login/"
LOGIN_REDIRECT_URL = '/content/'
LOGOUT_REDIRECT_URL = '/content/'

STATIC_URL = '/content/static/'

STATIC_ROOT = os.path.join(BASE_DIR, "static/")

# Media files
MEDIA_URL = '/content/media/'

MEDIA_ROOT = os.path.join(BASE_DIR, "mediafiles/")

api网关-〉nginx配置文件

server_name api.mydomain.com;
  location /auth/ {
    proxy_pass http://django_app:8002/;
    proxy_set_header Host $http_host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
  }

相关问题