user6354141
user6354141

Reputation:

Django + uWSGI + nginx url mapping

I want to run Django with uWSGI behind a NGINX.

I will use Django as a API service which should live on this link: project.test/api The Django project itself is blank (1.9.6), just created a app, migrated and created a superuser.

My Project structure looks like this:
/vagrant/api/here-lives-whole-django
/vagrant/api/uwsgi_params
/vagrant/frontend/some-frontend-work-seperated-from-django

My NGINX setup looks like this:

upstream testing {
    server 127.0.0.1:8000;
}

server {
    listen   80;

    server_name www.testing.test;

    charset  utf-8;

    client_max_body_size  75M;

    access_log  /var/log/nginx/www.testing.test.access.log;
    error_log  /var/log/nginx/www.testing.test.error.log;

    location /api/ {
        include /vagrant/api/uwsgi_params;
        uwsgi_pass testing;
    }

    location / {
        root /vagrant/frontend;
    }
}

The uwsgi_params file:

uwsgi_param  QUERY_STRING       $query_string;
uwsgi_param  REQUEST_METHOD     $request_method;
uwsgi_param  CONTENT_TYPE       $content_type;
uwsgi_param  CONTENT_LENGTH     $content_length;

uwsgi_param  REQUEST_URI        $request_uri;
uwsgi_param  PATH_INFO          $document_uri;
uwsgi_param  DOCUMENT_ROOT      $document_root;
uwsgi_param  SERVER_PROTOCOL    $server_protocol;
uwsgi_param  REQUEST_SCHEME     $scheme;
uwsgi_param  HTTPS              $https if_not_empty;

uwsgi_param  REMOTE_ADDR        $remote_addr;
uwsgi_param  REMOTE_PORT        $remote_port;
uwsgi_param  SERVER_PORT        $server_port;
uwsgi_param  SERVER_NAME        $server_name;

My Django url pattern:

urlpatterns = [
    url(r'^admin/', admin.site.urls),
]

Atm. Im running Django with following command:
uwsgi --socket :8000 --wsgi-file wsgi.py

Im able to reach Django but when I try to access
www.testing.test/api/admin
I get a 404 (debug from Django).

Page not found (404)
Request Method: GET
Request URL:    http://www.testing.test/api/admin
Using the URLconf defined in testing.urls, Django tried these URL patterns, in this order:
^admin/
The current URL, api/admin, didn't match any of these.

I know it will be something very simple for people who are used to this stuff, forgive me because Im new.

Ps. I found some similar questions where people worked with

uwsgi_param SCRIPT_NAME /api;
uwsgi_modifier1 30; 

But this just made my Django tell me a 404 with

Request URL:    http://www.testing.test/api/api/admin

when I requested

Request URL:    http://www.testing.test/api/admin

Upvotes: 7

Views: 3745

Answers (1)

grochmal
grochmal

Reputation: 3027

I had trouble to understand your question but basically it resumes to this: I want nginx to pass all calls to /api/ to django but django is receiving the URL with /api/ prefixed.


nginx trick (does not work for internal URLs)

I'd use nginx's rewrite to solve this

location /api/ {
    rewrite ^/api/(.*) /$1  break;
    include /vagrant/api/uwsgi_params;
    uwsgi_pass testing;
}

It shall drop the /api/ part of the URL and remain in the block to uwsgi_pass into Django.


django solution (dirty in my opinion)

The above works for the first URL going into django. Yet, django is clueless about the prefix that was removed and will have trouble to generate URLs to itself. That might not be a problem in some simple APIs but it would be a problem more often than not.

I guess, the only viable way is to add the prefix to the base URLconf.

from django.conf.urls import include

mypatterns = [
    url(r'^admin/', admin.site.urls),
]

urlpatterns = [
    url(r'^api/', include(mypatterns)),
]

Although, I feel this is a very dirty solution.

Upvotes: 8

Related Questions