Как сделать перезапись URL для структуры папок - PullRequest
0 голосов
/ 11 мая 2019

У меня есть приложение Django, и у меня есть следующие варианты использования:

  1. Локальная разработка.Поскольку мое приложение в основном простое, я предпочитаю обычный manage.py runserver подход.Поэтому я ожидаю, что мое приложение будет работать для этого случая.
  2. Производственная среда.У нас есть один веб-сервер и хост-инструменты под разными URL-адресами, например https://myserver.com/tool1, https://myserver.com/tool2 и т. Д. Поэтому я хотел бы поместить свое приложение в эту структуру
  3. (теоретически) За исключением варианта использования 2,Я могу хотеть разместить приложение в своем собственном домене, например https://tool.myserver.com

Но когда я попытался это сделать, у меня возникла проблема со статическими файлами (вздох!), Потому что если у меня есть STATIC_URL как относительный путь STATIC_URL='static/', тогда он не работает для "вложенных" страниц (то есть, если я на myserver.com/tool1/page, тогда статический URL будет отображаться на myserver.com/tool1/page/static, что неверно).С другой стороны, если я использую абсолютный путь STATIC_URL='/static/', то для случая 2 он вообще не работает, потому что приложение Django ничего не знает о /tool1 части URL, где он расположен.

Я могу использовать два разных варианта для STATIC_URL в зависимости от среды и жесткого кода STATIC_URL='/tool1/static/', но тогда тот же код не будет работать для случая 3 ...

Как мне обращатьсяэта ситуация?

UPD

На самом деле я понял, что это больше похоже на общий вопрос nginx + backend, чем на Django.Потому что в конце дня веб-страница, созданная бэкендом, скорее всего, будет иметь src="/static/...." (если я не добавлю несколько хаков в бэкэнд для вставки префикса / tool1).И мне интересно, как это обычно обрабатывается?Есть способ заменить фактический HTML-контент в nginx, но это действительно повлияет на производительность ...

UPD2

Похоже, что многие люди неправильно поняли мой вопрос, думая, что единственная проблема заключается встатические файлы.Однако это был просто пример, потому что, как правильно сказал Иван, такая же проблема существует и со ссылками.Обычно на странице у меня есть ссылки типа a href="/category/post?id=1".И, очевидно, когда сайт открывается как my.domain/tool1, это преобразуется в my.domain/category..., что неправильно (я хочу, чтобы он указывал на my.domain/tool1/category....)

Ответы [ 3 ]

1 голос
/ 10 июля 2019

Обработка STATIC_URL из приложения django может привести к дополнительным расходам.Поскольку у вас есть несколько подкаталогов, почему бы не обслуживать статические файлы только из одного из них?Нет необходимости совпадать с подкаталогом при обслуживании статических файлов.

Допустим, если вы установите STATIC_URL следующим образом:

STATIC_URL = "/tool1/static/"

Тогда вы можете просто настроить NGINX следующим образом:

server {
    listen 80

    server_name *.myserver.com;

    location /tool1/static/ {
        root /path/to/STATIC_ROOT;
    }

    location / {
        proxy_pass http://localhost:8000;  # <-- No trailing slash to make it work with gunicorn
    }

    location /tool2/ {
        proxy_pass http://localhost:8000;
        proxy_set_header SCRIPT_NAME /tool2;  # <-- For serving in sub path
    }

    location /tool1/ {
        proxy_pass http://localhost:8000;
        proxy_set_header SCRIPT_NAME /tool1; # <-- For serving in sub path
    }

}

А в настройках обновить STATIC_URL до /tool1/static/.Также убедитесь, что ваш STATIC_ROOT указывает на правильный путь, где статические файлы будут находиться на сервере.Наконец, перед развертыванием статических файлов необходимо запустить collectstatic command, чтобы поместить статические файлы в каталог STATIC_ROOT, а затем перезапустить сервер NGINX.

Обновление: Не рекомендуется использовать жестко запрограммированный URL.Вместо этого в шаблоне следует использовать тег {% URL '<url_name> '%} или reverse() в коде Python.Так что, Джанго сам разрешит URL.Когда он находится в /tool1 местоположении, URL-адреса будут преобразованы в /tool1/url_name/ и /tool2/url_name, когда вы находитесь в местоположении /tool2 (на основе SCRIPT_NAME).

0 голосов
/ 10 июля 2019

Кажется, что нет действительно хорошего способа решить это.Однако я нашел несколько вариантов:

Всегда используйте один канонический адрес (лично желательно)

Я должен спросить себя: «Почему вы хотите, чтобы ваш инструмент был доступен наи https://myserver.com/tool1 и https://tool1.myserver.com? ".И на самом деле у меня нет никаких причин, почему он должен быть доступен отдельно в одно и то же время.Поэтому просто выберите «канонический» адрес и настройте правильные перенаправления:

Если домен канонический:

    server_name myserver.com
    location /tool1/ {
            rewrite ^/tool1/?(.*)$ https://tool1.myserver.com/$1 permanent;
    }

Если папка каноническая:

    server_name tool1.myserver.com
    location / {
            rewrite ^ https://myserver.com/tool1$request_uri? permanent;
    }

Тогда на бэкэндесторона использует любую одну опцию STATIC_URL, соответствующую каноническому адресу (то есть /static для субдомена или /tool1/static для папки)

Дополнительные заголовки или параметры URL

Если есть причина (скажите мне, почему!) Не использовать перенаправления и использовать оба адреса в игре, то, как упоминал Руддра, можно добавить дополнительные заголовки, а затем использовать их на стороне сервера для генерации немного отличающихся друг от другастраницы:

location /tool1/ {
    <proxy_pass something>
    proxy_set_header SCRIPT_NAME /tool1;
}

Тот же подход можно использовать, если вы выбираете папку в качестве канонического адреса, тогда вы можете избежать жесткого кодирования tool1 в бэкэнде.Тогда, возможно, вы можете использовать либо собственный заголовок, либо дополнительный параметр url, например ?from=domain [1] , который может обрабатываться в бэкэнде.Здесь у меня нет готового решения, так как для меня предпочтительнее поддомен.

0 голосов
/ 09 июля 2019

Я рекомендую размещать ваши статические файлы в сервисе хранения, таком как AWS S3, Google Cloud Storage и т. Д. Таким образом, он всегда доступен для любого URL, который у вас есть (вложенный, поддомен и т. Д.)

Пример настройки(может потребоваться несколько дополнительных шагов):

  • Изменить settings.py:

    STATIC_URL = 'https://storage.googleapis.com/your_bucket/static/'

    STATIC_ROOT = os.path.join(BASE_DIR, "staticfiles")

    STATICFILES_DIRS = (os.path.join(BASE_DIR, 'static'),)

  • Перед развертыванием приложения запустите manage.py collectstatic --noinput

  • Скопируйте файлы из вашей папки staticfiles в службу хранения и убедитесь, что ониобщедоступны
  • Разверните ваше приложение

PS Я нахожу whitenoise, чтобы действительно помочь со статическими размерами файлов и облегчить развертывание

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...