5

I have django app running in subpath example.com/api/. Most of it is rest API (I use django-rest-framework), and all requests are working correctly. But static files has wrong paths everywhere - in admin panel, and in requests page (in django-rest-framework you have frontend to investigate things). Django somehow thinks, that all static files are in example.com/back/static/, when they are in example.com/api/back/static/.

Also example.com/api/admin redirects to example.com/admin/login/, but after manually going to example.com/api/admin/login/ everything works smoothly (but still there are no styles).

My stack is nginx + Django 2.0.5 running in docker container.

Nginx configuration:

location /api/ {
    proxy_pass            http://localhost:8000/;
    proxy_read_timeout    90;
    proxy_connect_timeout 90;
    proxy_set_header      Host $host;
    proxy_set_header      X-Real-IP $remote_addr;
    proxy_set_header      X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header      Proxy "";
}

When it comes to Django STATIC_URL is set to os.path.join(BASE_DIR, "static/"), FORCE_SCRIPT_NAME is not set, but when set, it's not working at all.

Any ideas?

[Update]

After some hours of fight, I gave up. The problem is connected with uwsgi not recognizing that it's running in subpath. Here are some links which can be useful for someone with similar problem:

Run django app via nginx+uwsgi in a subpath

Running Django on a subpath

Serving multiple Django applications with Nginx and Gunicorn

Django WSGI routing

I gave up and just created separate subdomain for this project.

Ian Sowinski
  • 96
  • 1
  • 5
  • Do you want the django app to serve its own static files or do you want nginx to serve them (better)? – user2390182 Jul 04 '18 at 09:41
  • @schwobaseggl I want to use django to serve its own static files – Ian Sowinski Jul 04 '18 at 09:50
  • Your `STATIC_URL` setting looks like you want it to be your `STATIC_ROOT` setting. Then set `STATIC_URL` to `/api/back/static/`. Make sure to call `collectstatic` on the server. Also set your `LOGIN_URL` setting to `/api/admin/login/` – user2390182 Jul 04 '18 at 09:52
  • It doesn't work, seems like django is ommiting 'api' subpath in this requests. – Ian Sowinski Jul 04 '18 at 10:17
  • you must declare STATIC_ROOT and STATIC_URL in settings.py of your site. – vorujack Jul 04 '18 at 10:33
  • @vorujack I did it, It seams that problem is in generating paths - django thinks that it's in root path, nginx passes everything to it, and it works, but when django generates urls, it doesn't care about `api/` subpath and omits it. – Ian Sowinski Jul 04 '18 at 10:48
  • for static use /api/static/ in settings static_url – vorujack Jul 04 '18 at 11:03

3 Answers3

3

This is a known issue in Django.

Expected behavior

Outside world (nginx\uwsgi\whatever) should have SCRIPT_NAME header (which would be equal to /api in your case) and forward it to Django.

Django should respect this header and add it for the URLs generated with {%url ... %} tag (which it does already) AND for static file links generated with {% static ... %} (which does not work, see mentioned issue).

To workaround this you can append prefix directly to STATIC_URL: STATIC_URL = '/api/static'... But this is a dirty hack, I agree. The proper way is to to have it fixed on Django side.

Also see https://stackoverflow.com/a/57009760/1657819, may be a bit related

The Godfather
  • 4,235
  • 4
  • 39
  • 61
1

If you proxy_pass a location in Nginx and add a URI to your proxy_pass directive you are telling Nginx to remove that from the original request URL and replace that part of the request URI with your proxy_pass URI. So this:

location /api/ {
    proxy_pass            http://localhost:8000/;

Tells Nginx that a request to example.com/api/path/to/whatever/ should be proxied to http://localhost:8000/path/to/whatever/

If you want the original unaltered request URI passed to the proxy then remove the / from the end of the proxy_pass directive

miknik
  • 5,748
  • 1
  • 10
  • 26
0

add this code to your nginx configuration:

location /static/ {
    alias /path/static/;
}

you should define the location of static files, in order to read it.

Ali
  • 2,541
  • 2
  • 17
  • 31