nginx通过uWSGI在一个子目录中提供Django

时间:2016-03-04 09:31:06

标签: django nginx uwsgi subdirectory

我已经完成了一些以前的主题: How do I set subdirectory in nginx with Django how to deploy django under a suburl behind nginx Serving flask app on subdirectory nginx + uwsgi

基本教训是,您只需配置您的站点(可用)即可实现此目的。我现在尝试了各种各样的排列

server {
    listen 80;
    server_name www.example.com;

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

    location /static/ {
        root /path/to/project;
    }

    location /project/ {
        root            /path/to/project;
        include         /etc/nginx/uwsgi_params;
        uwsgi_param     SCRIPT_NAME /project;
        uwsgi_modifier1 30;
        uwsgi_param PATH_INFO "$1";
        uwsgi_pass      unix:/tmp/project.sock;
    }
}

当我将位置定义为" /"时,一切都运行得很好。 (并删除SCRIPT_NAME,modifier1,PATH_INFO和root并不重要。但是尝试使用子目录总是会导致找不到页面(404):

Request URL:    http://www.example.com/project/project

(编辑)它正在为请求添加目录。我怎么不搞清楚?

(尝试使用forced_script_name - 不应该使用它并给出其他类型的头痛 - 以及uwsgi配置设置)

编辑:

location /project/ {
    root            /path/to/project;
    include         /etc/nginx/uwsgi_params;
    uwsgi_param     SCRIPT_NAME /project;
    uwsgi_pass      unix:/tmp/project.sock;
}

不起作用......套接字在那里,当我配置/时工作 - 我只是看不到我错过的东西。

更新:

location ~ /project(?<path_info>/.*|$) {
    include         /etc/nginx/uwsgi_params;
    uwsgi_pass      unix:/tmp/project.sock;
    uwsgi_param     PATH_INFO $path_info;
    uwsgi_param     SCRIPT_NAME /project;
}

这会加载网站,但所有链接都指向http://example.com/link/to/something而不是http://example.com/project/link/to/something

5 个答案:

答案 0 :(得分:5)

uWSGI中不推荐使用nginx uwsgi_modifier1

您的目标是能够从任何地方托管wsgi应用,而无需对应用进行调整以说明其提供的位置。

在uWSGI中执行此操作的当前方法是为每个URI应用程序组合映射挂载点,如下所示:

[uwsgi]
socket = 127.0.0.1:3031
; mount apps
mount = /app1=app1.py
mount = /app2=app2.py
; rewrite SCRIPT_NAME and PATH_INFO accordingly
manage-script-name = true

Hosting multiple apps in the same process (aka managing SCRIPT_NAME and PATH_INFO)

mount可取代module

特别是Django,

; Before
module = django_app.wsgi:application
; After
mount = /django_app=django_app.wsgi:application
manage-script-name = true

答案 1 :(得分:0)

首先,删除uwsgi_modifier1 30;。 Django将自己处理SCRIPT_NAME并且不需要由uWSGI重写PATH_INFO。如果uWSGI未从标题中删除SCRIPT_NAME,则可能会有害。

其次,从nginx配置中删除uwsgi_param PATH_INFO "$1";PATH_INFO已在uwsgi_params文件中定义,如果您将$document_uri传递给django,则应为$1(因为它位于uwsgi_params中),而不是SCRIPT_NAME

在调整之后,django应该将SCRIPT_NAME视为URL前缀,并将调整url dispatcher和url反转为。

答案 2 :(得分:0)

如果应用程序如此简单以至于简单的&#34; /前缀&#34;可以添加到urls.py中的一行,然后我更喜欢这个简单的解决方案。

否则&#34; /前缀&#34; 必须追加网站中您网站的记录中的domain表格在Django admin中。该域应该是&#34; example.com/project"使用第二种解决方案,因为Django必须知道域和前缀,尤其是正确的重定向。当然,必须从网络服务器的请求URL中删除前缀,就像现在在nginx设置中一样。

我通常会将此类部署的验证分为两个问题:

  • 是否向Web服务器(nginx)报告Django的预期更短或更长的URL?
  • 知道Django是否有完整的基本URL并且是否一直在所有网页中使用它?

我同时使用nginx日志和Django日志记录来查看哪些最终被错误配置。 (你没有写过足够重要的信息。)

应该测试的一个重要案例是:验证要求身份验证的网页是否会被正确地来回重定向到登录页面,即使您在注销后尝试使用这些URL也是如此。

更多详细信息,请参阅similar question

答案 3 :(得分:0)

最终放弃试图“巧妙地”做到这一点。

最终的解决方案是创建一个设置变量,我将其添加到static_url和projects urls.py文件中。没有SCRIPT_NAME或nginx方面的任何复杂内容。

答案 4 :(得分:0)

最新Nginx / uWSGI版本的最干净方法

由于uwsgi_modifier1 30在最新版本中已被删除,而且我觉得安装点的内容太过hacky,因此我不得不使用newer method来在子目录:

uWSGI配置:

[uwsgi]
socket =        /tmp/project.sock
route-run =     fixpathinfo:

Nginx配置:

location /project {
    include         /etc/nginx/uwsgi_params;
    uwsgi_pass      unix:/tmp/project.sock;
    uwsgi_param     SCRIPT_NAME /project; # Pass the URL prefix to uWSGI so the "fixpathinfo:" route-rule can strip it out
}

注意:fixpathinfo:要求将PCRE支持编译到 uWSGI。

因此,如果一切正常,请尝试安装libpcre和libpcre-dev,然后使用pip install -I --no-cache-dir uwsgi重新编译uwsgi。 uWSGI的内部路由子系统要求在 编译/安装uWSGI之前安装PCRE库。 More information on uWSGI and PCRE.