Django在子目录 - 管理站点不起作用

时间:2017-07-08 14:05:17

标签: python django

我已将Django项目部署在服务器上的子目录中(dns_name_of_my_page / notes)。我可以通过dns_name_of_my_page / notes / app /访问此项目中的应用。不幸的是,如果整个Django项目位于托管服务器上的public_html中的子目录'notes'中,则admin站点无效。当我进入管理站点(dns_name_of_my_page / notes / admin /)时,重定向到URL而没有子目录的名称(dns_name_of_my_page / adminlogin /?next = // admin /),这是不可接受的。它应该是dns_name_of_my_page / notes / adminlogin /?next = / notes / admin /

以下是我在项目中的URL配置:

urlpatterns = [
    url(r'^/?app/?', include('app.urls')),
    url(r'^/?$', views.index, name='index'),
    url(r'^/?admin/?', admin.site.urls),
]

以下是我的应用中的网址配置:

urlpatterns = [
    url(r'^$', views.index, name='index'),
    url(r'^(?P<num>[0-9]+)/?', views.num, name='num'),
]

我试图设置

FORCE_SCRIPT_NAME = '/notes/'

SUB_SITE = "/notes/"
在settings.py中

但它没有帮助我。

在子目录中运行Django应用程序时遇到过这种问题吗?

1 个答案:

答案 0 :(得分:3)

今天我被卷入了这个问题,虽然有很多类似的问题[1],但答案有点像我解决这个问题的经验。

您的问题中缺少一个细节,即您正在处理的服务器设置。为了解释我的解决方案,它有助于理解它如何与Django方面结合使用。

我一直在解决的问题包括访问Django的管理员(以及大多数其他应用程序,如Auth)这个问题,就是让服务器充当多个独立的django项目的主机。目的是让URI以http://my.server.com/project_name/foo/bar/ [2]开头。就每个项目而言,它在my.server.com上运行,并且正在处理/ foo / bar(大多数生产/单应用程序系统中的情况,以及使用manage.py runserver进行本地开发)

我正在使用NGinx作为反向代理,侦听我的域名的端口80和443。在该服务器中,我有一个location设置代理到每个子项目的Nginx服务+ Gunicorn。

nginx默认位置配置如下所示:

location /project_name {
    proxy_set_header X-Forwarded-Protocol $scheme;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header Host $http_host;
    proxy_set_header X-Scheme $scheme;
    proxy_set_header X-Forwarded-For $remote_addr;

    proxy_pass http://localhost:7001/;
}

每个项目自己的nginx + gunicorn服务的设置与此主题并不特别相关,但正如您所看到的那样,它在自己的本地服务端口上呈现。

此配置将为http://my.server.com/foo/bar/提供有效请求。这使我们现在有信心Django将/ project_name /前缀添加到它在输出中生成的所有URL。

要做到这一点,您需要了解一些重要的设置,包括:

USE_X_FORWARDED_HOST = True
FORCE_SCRIPT_NAME = '/project_name/'

这会导致Django尊重nginx传递的标头更改,并触发它自己的进程来重写模板中{% url name %}标签的输出。

SESSION_COOKIE_PATH = '/project_name/'

这应该有助于将该域上的多个登录分开,并且意味着您可以登录一个项目,但不能登录到另一个项目(或使其混淆)。

STATIC_FILES_ROOT='\path\on\disk\as\in\your\nginx\config\for\static\'
STATIC_FILES_URL='/project_name/static/'
MEDIA_FILES_ROOT='\path\on\disk\as\in\your\nginx\config\for\media\'
MEDIA_FILES_URL='/project_name/media/'

这些处理`{%static blah%}类型模板标签和文件服务。

LOGIN_REDIRECT_URL='/project_name/'
LOGOUT_REDIRECT_URL='/project_name/'

这些处理使用Auth模块登录/退出服务的结果,并确保在登录或注销时将用户发送回项目站点的根目录。您可以轻松地根据自己的需要定制这些内容,包括使用url-conf样式的正则表达式字符串,例如我们将在下面为管理页面执行此操作

ADMIN_URL=r'^admin/'

此设置与您网站中的此行配对urls.py:

url(settings.ADMIN_URL, include(admin.site.urls)),   # default=r'^admin/'

这里的一个关键细节是正则表达式没有前面/后面,否则会尝试强制它返回主机名,因此FORCE_SCRIPT_NAME指定的更改将起作用。

另外,请注意不要在模板中以/开头的任何硬编码网址(相对或其他),因为Django模板输出更改不会捕获这些网址。

按照这种方法,我已经能够在三个不同的系统中部署这些项目,其中两个系统涉及它们作为该域或服务端口上唯一的django应用程序运行,其余的一个是这个共享域设置,除了更改每个位置的设置值之外,不需要任何其他内容。

使用您自己的代码示例采用此方法,我建议您正在寻找对以下内容的更改:

urlpatterns = [
    url(r'^admin/?', admin.site.urls),
    url(r'^app/?', include('app.urls')),
    url(r'^$', views.index, name='index'),
]

为了帮助搜索和匹配订单,我重新安排了管理员先来,而空/ home / root匹配模板最后来了。否则,您的FORCE_SCRIPT_NAME设置就会出现在正确的轨道上。

[1]例如multiple instances of django on a single domain; Is it possible to host multiple django projects under the same domain?; how to deploy django under a suburl behind nginx

[2]默认服务器实际上也处理SSL转换,因为服务在https上显示,但在内部,localhost端口(隐藏在机器防火墙后面)仅处理http。