Запустить приложение django через nginx + uwsgi в подпути
Я хочу запустить простой тестовый проект в псевдониме подкаталога на нашем сервере разработки. Базовая установка - 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 config:
server {
location /fancyprojectname/static {
alias /srv/fancyprojectname/static;
}
location /fancyprojectname/ {
uwsgi_pass unix://var/run/uwsgi/app/fancyprojectname/socket;
include uwsgi_params;
}
}
Edit
Итак, установка "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/", Django не может правильно соответствовать URL-адресам, даже если установлен SCRIPT_NAME.
Решение
Итак, это действительно проблема с 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 об отключении SCRIPT_NAME из PATH_INFO.
Сочетание этих настроек, похоже, работает, поскольку Django теперь может правильно генерировать AND и сопоставлять URL-адреса.
Ответы
Ответ 1
Это неверно:
Django, очевидно, не понимает, что он работает в псевдониме подкаталога, что полностью разрушает создание и разбор URL.
Джанго это понимает и прозрачно разбирается в этом. Сервер должен сам устанавливать 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.
Ответ 2
Если этот блок местоположения Nginx работает при размещении сайта Django в http://www.example.com/
(ваш базовый домен):
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;
}
... и нет необходимости устанавливать FORCE_SCRIPT_NAME в настройках Django.
Литература:
Ответ 3
Теперь, когда uwsgi_modifier1 30
удаляется в последних версиях Nginx и uWSGI (и мне не нравилось использование некоторых правил хакерского перезаписи), я нашел более новый метод, чтобы заставить его работать:
Конфигурация uWSGI:
[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, а затем переустановите uwsgi с pip install -I --no-cache-dir uwsgi
. Подсистема внутренней маршрутизации uWSGI требует, чтобы библиотека PCRE была установлена до компиляции/установки uWSGI. Дополнительная информация о uWSGI и PCRE.