Запустить приложение 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.