16

我想在我们的开发服务器上的子目录别名中运行一个简单的测试项目。基本设置是一个 nginx,其位置将子目录中的所有内容传递给 wsgi 应用程序。

Django 显然不明白它运行在一个子目录别名中,这完全破坏了 URL 的生成和解析。
我在文档中找不到任何类似前缀的设置,我的 google fu 也没有太大帮助......所以我在这里问。

我唯一找到的是设置 FORCE_SCRIPT_NAME 至少修复了 URL 生成。(参见:http ://docs.webfaction.com/software/django/config.html#mounting-a-django-application-on-a-subpath )
遗憾的是,这并不能修复 urlconf 解析,即使提到的网站建议那。

是否可以在子目录别名中运行 django 应用程序,如果可以,如何?

nginx配置:

server {
        location /fancyprojectname/static {
                alias /srv/fancyprojectname/static;
        }

        location /fancyprojectname/ {
                uwsgi_pass unix://var/run/uwsgi/app/fancyprojectname/socket;
                include uwsgi_params;
        }
}

编辑

因此,设置“uwsgi_param SCRIPT_NAME /fancyprojectname;” 在 nginx 位置使 FORCE_SCRIPT_NAME 变得不必要 - 遗憾的是 URL 匹配仍然不起作用。

from django.conf.urls import patterns, include, url

# Uncomment the next two lines to enable the admin:
from django.contrib import admin
admin.autodiscover()

urlpatterns = patterns('',
    # Uncomment the admin/doc line below to enable admin documentation:
    # url(r'^admin/doc/', include('django.contrib.admindocs.urls')),

    # Uncomment the next line to enable the admin:
    url(r'^admin/', include(admin.site.urls)),
)

我认为发生了什么:由于管理员正则表达式以“^admin”开头并且实际 URL 是“fancyprojectname/admin/”,因此即使设置了 SCRIPT_NAME,Django 也无法正确匹配 URL。

解决方案

所以,这确实是 SCRIPT_NAME 的问题。

WSGI 规范说明如下:

SCRIPT_NAME 请求 URL 的“路径”的初始部分,对应于应用程序对象,以便应用程序知道其虚拟“位置”。如果应用程序对应于服务器的“根”,这可能是一个空字符串。

PATH_INFO 请求 URL 的“路径”的其余部分,指定应用程序中请求目标的虚拟“位置”。如果请求 URL 以应用程序根目录为目标并且没有尾部斜杠,则这可能是一个空字符串。

Nginx 不会自动设置 SCRIPT_NAME,所以无论如何都需要设置。之后 PATH_INFO 是错误的,因为在默认设置中 Nginx 将其设置为 $document_uri,这将是完整的 URL。

“uwsgi_modifier1 30;” 告诉 Nginx 设置 UWSGI_MODIFIER_MANAGE_PATH_INFO,这反过来告诉 UWSGI 去除 PATH_INFO 的 SCRIPT_NAME。

这些设置的组合似乎有效,因为 Django 现在可以正确生成和匹配 URL。

4

3 回答 3

8

这是错误的:

Django 显然不明白它运行在一个子目录别名中,这完全破坏了 URL 的生成和解析。

Django确实理解这一点,并且透明地处理它。服务器应该自行设置SCRIPT_NAME:您发现自己正在使用的事实FORCE_SCRIPT_NAME表明问题出在您的 Nginx 配置中,而不是在 Django 中。

我怀疑问题在于使用location,而不是更合适的指令。不幸的是,我不是 Nginx/uwsgi 方面的专家。在 Apache/mod_wsgi 中,您可以这样做:

WSGIScriptAlias /mysite /usr/local/django/mysite/apache/django.wsgi

告诉 mod_wsgi 该站点从 开始mysite,而不是根。几乎可以肯定 nginx/uwsgi 有一个类似的命令。

于 2012-07-02T11:18:10.643 回答
6

http://www.example.com/如果在(您的基本域)托管 Django 站点时此 Nginx 位置块有效:

location / {
    uwsgi_pass unix:/tmp/fancyprojectname.socket;
    include /etc/nginx/uwsgi_params;
}

然后这将适用于http://www.example.com/subpath/(您的基本域上的子路径):

location /subpath {
    uwsgi_pass unix:/tmp/fancyprojectname.socket;
    uwsgi_param SCRIPT_NAME /subpath; # explicitly set SCRIPT_NAME to match subpath
    uwsgi_modifier1 30; # strips SCRIPT_NAME from PATH_INFO (the url passed to Django)
    include /etc/nginx/uwsgi_params;
}

...并且无需在您的 Django 设置中设置 FORCE_SCRIPT_NAME 。

参考:

于 2016-04-12T11:59:32.240 回答
5

现在,在最新版本的 Nginx 和 uWSGIuwsgi_modifier1 30中已将其删除(而且我不想使用一些 hacky 的重写规则),我必须找到一种更新的方法来让它工作:

uWSGI 配置:

[uwsgi]
# Requires PCRE support compiled into uWSGI
route-run = fixpathinfo:

Nginx 配置

server {
    location /fancyprojectname/static {
        alias /srv/fancyprojectname/static;
    }

    location /fancyprojectname {
        uwsgi_pass unix://var/run/uwsgi/app/fancyprojectname/socket;
        uwsgi_param SCRIPT_NAME /fancyprojectname; # Pass the URL prefix to uWSGI so the "fixpathinfo:" route-rule can strip it out
        include uwsgi_params;
    }
}

如果无法解决:尝试安装 libpcre 和 libpcre-dev,然后使用pip install -I --no-cache-dir uwsgi. uWSGI 的内部路由子系统需要在编译/安装 uWSGI之前安装 PCRE 库。有关 uWSGI 和 PCRE 的更多信息。

于 2018-05-29T15:49:15.937 回答