Nginx отвечает 404 not found на медиа URL Django в preprod, dev ok

У меня есть вполне стандартное Django приложение с Vuejs фронтендом.

У меня есть различные среды (preprod/dev), в которых есть функции загрузки/выгрузки файлов.

Для файлов все работает нормально, поскольку они возвращаются через стандартные представления API во вложении (Content-Disposition: attachment). Однако когда дело доходит до изображений, например, фотографий профиля, возникает проблема.

В разработке (DEBUG=True) я имею следующее :

from django.conf import settings
from django.conf.urls.static import static
from django.urls import include, path

from backend.applications.base.views.authentication_views import LoginAPIView, LogoutAPIView

urlpatterns = [
    path("api/login", LoginAPIView.as_view()),
    path("api/logout", LogoutAPIView.as_view()),
    path("api/base/", include("backend.applications.base.urls")),
    path("api/contact/", include("backend.applications.contact.urls")),
    path("api/helpdesk/", include("backend.applications.helpdesk.urls")),
    path("api/inventory/", include("backend.applications.inventory.urls")),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)  # For serving media files when DEBUG=True

и изображения обслуживаются правильно (нет nginx в режиме dev, только frontend и backend dev серверы django's runserver).

Мой preprod состоит из контейнера nginx, который обслуживает мой собранный vuejs frontend, и контейнера backend, который содержит мое Django (DEBUG=False) приложение (которое запускается с gunicorn на этот раз, вот так: gunicorn backend.wsgi:application --bind 0.0.0.0:8000 --access-logfile="-").

Перед тем, как попытаться обслуживать изображения, у меня была такая конфигурация nginx :

http {
    client_max_body_size 5M;

    upstream backend_api {
        server backend:8000;
        # 'backend' is the name of the backend service in my docker-compose config
    }

    server {
        listen 80;

        include /etc/nginx/mime.types;

        root /usr/share/nginx/html;
        index index.html;

        location = /favicon.ico {
            access_log off;
            log_not_found off;
        }

        location /api {
            proxy_pass http://backend_api;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_redirect off;
        }

        location / {
            try_files $uri $uri/ /index.html;
        }
    }
}

Затем я подумал, что /media запросы также должны передаваться бэкенду, и я изменил

location /api
<
location ~ ^/(api|media)/ {

Мои /api URL по-прежнему обрабатываются правильно, но на /media URL отвечают 404 :

trying to load profile pictures of my user(s) in a kanban view (пытаюсь загрузить фотографии профиля пользователя(ей) в представление канбан).

Также попытка прямо http://localhost/media/base/users/8/picture.jpg непосредственно в браузере не работает :

enter image description here enter image description here

Отсюда я не знаю, что делать для решения проблемы. Если чего-то не хватает, укажите это, и я обновлю пост. Я думаю, это потому, что в моих urlpatterns нет маршрута media/, но я не знаю, как мне с этим справиться...

Заранее спасибо за помощь!

Django не обслуживает статические и медиа файлы с помощью runserver, для этого вам понадобится WhiteNoise. См. http://whitenoise.evans.io/en/stable/. Однако WhiteNoise не подходит для обслуживания загруженных пользователем медиафайлов. См. http://whitenoise.evans.io/en/stable/django.html#serving-media-files

(Как вариант, пропустить whitenoise и разместить статические/медиа файлы через NGINX)

Вам не следует размещать свой сервер на py manage.py runserver. Это небезопасно. См. Почему бы не использовать "runserver" для производства в Django? и https://docs.djangoproject.com/en/dev/ref/django-admin/#runserver

Вместо этого используйте что-то вроде Gunicorn.

Смотрите https://docs.djangoproject.com/en/4.1/howto/deployment/wsgi/gunicorn/

(Или официантка, альтернатива для окон)

https://pypi.org/project/django-waitress/

Для размещения статических/медиа файлов с помощью nginx, вставьте это в conf вашего nginx:

    location /media  {
        alias /PATH/TO/DIRECTORY; #Absolute path.
    }

И в файле settings.py установите корень медиа в ту же директорию.

Вернуться на верх