在子文件夹上托管 Django

Posted

技术标签:

【中文标题】在子文件夹上托管 Django【英文标题】:Host Django on subfolder 【发布时间】:2018-06-05 01:58:10 【问题描述】:

我已经使用 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”的内容。

【问题讨论】:

您要查找的设置是 FORCE_SCRIPT_NAME - 您也可以让 nginx 将标头 X-Script-Name 设置为 /my_app 【参考方案1】:

我的评论没有显示完整的图片。当我在子文件夹上运行 Django 站点时,我喜欢使用动态配置,这样您仍然可以直接访问机器(无需代理)并拥有一个正常工作的网络应用程序。这可以帮助调试像这样难以在开发中重现的棘手问题。

如果您无法传递标头或修改 wsgi.py,您仍然可以在 Django 设置中设置FORCE_SCRIPT_NAME

三个步骤:

    在网络服务器前面设置一个代理,将子文件夹从 URL 中剥离出来 设置 X-Script-Name 标头,以便您的 Django 站点生成其 url,其前面带有 /myapp/ - 确保您使用的是 % url % 标记和 reverse,而不是硬编码!李> 修改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:

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)

【讨论】:

如果这在几年前有效,现在就不再适用了。 @JJK - 这个配置应该仍然有效。我对代理服务器的 NGINX 配置做了一个小的编辑,应该可以简化一些事情。这里假设您在https://mywebapp.com/ 有一个工作应用程序,并且有一个单独的域设置子文件夹(假设它是https://user-facing-domain.com/my_app/)。 https://user-facing-domain.com 的代理运行上面的 NGINX 配置。 ...“将子文件夹从 URL 中剥离”... 似乎是其中的重要组成部分! 这似乎是部分解决方案。 CSS 不起作用,因为页面正在寻找 /static。 @Brendon - 对于您的用例,您需要创建一个存储后端,在确定STATIC_URL 时考虑SCRIPT_NAME。请记住,它可能需要在开发和生产之间进行不同的处理。我认为使用 CDN 处理静态文件时不会出现这个问题。

以上是关于在子文件夹上托管 Django的主要内容,如果未能解决你的问题,请参考以下文章

从本地计算机运行 Web 应用程序并在外部服务器上托管文件

Django VirtualHosting:如何在一个 VPS 上托管具有不同域的多个 django 项目

在端口 80 上托管多个网站

如何解决 Heroku 上托管的 django 项目中的迁移问题?

没有显示 Apache 和 mod_wsgi 的 Ubuntu VM 上托管的 Django 应用程序

AWS Elastic Beanstalk 使用 Django 在部署的 EC2 服务器上托管 PostgreSQL