使用Nginx/Fastcgi在子URL下部署Django

9
我真的无法想象如何在Nginx/fastcgi下部署django站点到非根目录,例如http://localhost:8080/myproject/而不是http://localhost:8080/。我看到的所有示例都假定Apache或挂载在站点的根目录。这是我nginx.conf文件的相关部分:
server {
    listen 8080;
    server_name localhost;

    location /myproject/ {
        # host and port to fastcgi server
        fastcgi_pass 127.0.0.1:3030;

        fastcgi_param  QUERY_STRING       $query_string;
        fastcgi_param  REQUEST_METHOD     $request_method;
        fastcgi_param  CONTENT_TYPE       $content_type;
        fastcgi_param  CONTENT_LENGTH     $content_length;

        #fastcgi_param  SCRIPT_NAME        $fastcgi_script_name;
        fastcgi_param  PATH_INFO          $fastcgi_script_name;
        fastcgi_param  REQUEST_URI        $request_uri;
        fastcgi_param  DOCUMENT_URI       $document_uri;
        fastcgi_param  DOCUMENT_ROOT      $document_root;
        fastcgi_param  SERVER_PROTOCOL    $server_protocol;

        fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
        fastcgi_param  SERVER_SOFTWARE    nginx/$nginx_version;

        fastcgi_param  REMOTE_ADDR        $remote_addr;
        fastcgi_param  REMOTE_PORT        $remote_port;
        fastcgi_param  SERVER_ADDR        $server_addr;
        fastcgi_param  SERVER_PORT        $server_port;
        fastcgi_param  SERVER_NAME        $server_name;
    }
}

以下是一个简单的 urls.py 文件:

from django.http import HttpResponse
from django.conf.urls.defaults import patterns

urlpatterns = patterns('',
    (r'^hello$', lambda request: HttpResponse('Hello world!')),

尝试访问http://localhost:8080/myproject/hello时出现404错误。我已经尝试了以下所有组合,但都没有成功:

  • 注释/取消注释fastcgi_param PATH_INFO $fastcgi_script_name;
  • 注释/取消注释fastcgi_param SCRIPT_NAME $fastcgi_script_name;
  • 在settings.py中设置FORCE_SCRIPT_NAME = '/myproject/'
3个回答

7

我自己也遇到了同样的问题-结果发现你在ServerFault上提供的链接指向的是Django更改文档,这是解决问题的关键。

Django >1.0使用SCRIPT_NAMEPATH_INFO来路由URL,正如文档中所解释的那样。因此,我采用了这个方法。对于一个名为“myproject”的项目,你想将其根目录设置为mydomain.com/myproject/,请尝试以下操作。

location ~ /myproject/(.*)$ {
    fastcgi_pass 127.0.0.1:8080;
    fastcgi_param  PATH_INFO /$1;
    SCRIPT_NAME /myproject;
}

我在另一个站点的全局配置文件中有其他fastcgi参数。因此,您的示例将类似于:
server {
    listen 8080;
    server_name localhost;

    location /myproject/ {
        # host and port to fastcgi server
        fastcgi_pass 127.0.0.1:3030;

        fastcgi_param  QUERY_STRING       $query_string;
        fastcgi_param  REQUEST_METHOD     $request_method;
        fastcgi_param  CONTENT_TYPE       $content_type;
        fastcgi_param  CONTENT_LENGTH     $content_length;

        fastcgi_param  SCRIPT_NAME        /myproject;
        fastcgi_param  PATH_INFO          /$1;
        fastcgi_param  REQUEST_URI        $request_uri;
        fastcgi_param  DOCUMENT_URI       $document_uri;
        fastcgi_param  DOCUMENT_ROOT      $document_root;
        fastcgi_param  SERVER_PROTOCOL    $server_protocol;

        fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
        fastcgi_param  SERVER_SOFTWARE    nginx/$nginx_version;

        fastcgi_param  REMOTE_ADDR        $remote_addr;
        fastcgi_param  REMOTE_PORT        $remote_port;
        fastcgi_param  SERVER_ADDR        $server_addr;
        fastcgi_param  SERVER_PORT        $server_port;
        fastcgi_param  SERVER_NAME        $server_name;
    }
}

使用相同的urls.py文件。到目前为止,我遇到的唯一问题是在保持DRY方面有轻微麻烦,例如当settings.py需要绝对URL时,Django不会考虑在URL上添加SCRIPT_NAME(考虑设置LOGIN_URL,设置MEDIA_URL)。
这可能很明显,但还要确保您有另一个位置指向静态和管理媒体。

@gsakkis,这有帮助到你吗? - Matt Luongo
它帮助了我...我使用这种方法在nginx.conf中将两个Web应用程序托管在同一服务器{}上。但我的问题是两者都需要不同的静态和媒体URL...在这里该怎么办? - codeVerine

3

试试这个配置

    location  /myproject {
    fastcgi_split_path_info ^(/myproject)(.*)$;
    fastcgi_pass 127.0.0.1:8080;
    include fastcgi_params;
}

在这里,fastcgi_params文件包含以下内容

    fastcgi_param  QUERY_STRING       $query_string;
    fastcgi_param  REQUEST_METHOD     $request_method;
    fastcgi_param  CONTENT_TYPE       $content_type;
    fastcgi_param  CONTENT_LENGTH     $content_length;

    fastcgi_param  SCRIPT_NAME        $fastcgi_script_name;
    fastcgi_param  REQUEST_URI        $request_uri;
    fastcgi_param  DOCUMENT_URI       $document_uri;
    fastcgi_param  DOCUMENT_ROOT      $document_root;
    fastcgi_param  SERVER_PROTOCOL    $server_protocol;

    fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
    fastcgi_param  SERVER_SOFTWARE    nginx/$nginx_version;

    fastcgi_param  REMOTE_ADDR        $remote_addr;
    fastcgi_param  REMOTE_PORT        $remote_port;
    fastcgi_param  SERVER_ADDR        $server_addr;
    fastcgi_param  SERVER_PORT        $server_port;
    fastcgi_param  SERVER_NAME        $server_name;

    fastcgi_param  PATH_INFO          $fastcgi_path_info;

    # PHP only, required if PHP was built with --enable-force-cgi-redirect
    fastcgi_param  REDIRECT_STATUS    200;

对我来说有效。

有关fastcgi_split_path_info的文档,请参见。


0

我因为自己也遇到了子URL问题而偶然发现了你的问题。我的服务器使用Apache作为主服务器,所以我的配置不同,但它可以工作。也许这会帮助某些人:

  • 端口80上的Apache(主Web服务器)
  • 本地主机上的nginx:3033(随机端口)
  • 本地主机上的manage.py fastcgi:3034

然后Apache配置看起来像这样(代理到nginx):

<Location /blogsite/>
    Order deny,allow
    Allow from all

    ProxyPass http://127.0.0.1:3033/
    ProxyPassReverse http://127.0.0.1:3033/
</Location>

而nginx的站点配置如下:

server {
    listen 127.0.0.1:3033;
    server_name localhost;

    location / {
        fastcgi_pass 127.0.0.1:3034;
        fastcgi_param PATH_INFO $fastcgi_script_name;
        fastcgi_param REQUEST_METHOD $request_method;
        fastcgi_param QUERY_STRING $query_string;
        fastcgi_param CONTENT_TYPE $content_type;
        fastcgi_param CONTENT_LENGTH $content_length;
        fastcgi_pass_header Authorization;
        fastcgi_intercept_errors off;
    }

    access_log  /var/log/nginx/blogsite.access_log;
    error_log   /var/log/nginx/blogsite.error_log;
}

我认为你遇到的问题是由于nginx配置的某些原因,而不是Django部署的问题。您可以尝试一下我发布的解决方案是否适用于您。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接