By using our website, you agree to our privacy policy

Deploy Django App in Sub Directory Using OpenShift

Deploy Django App in Sub Directory Using OpenShift

When you are using OpenShift, you will be using routes to expose a route from a service. Let’s say you want to expose a path in When you do that for a django application(without any reverse proxy server), it usually becomes a problem, because the sub directory does not work well with Django’s urls. You will probably face error 404 page not found.

If you are not using NGINX/Apache or any other reverse proxy server to serve the django application, you will not be able to set X-SCRIPT-NAME. To me, it does not make sense to use reverse proxy in pods when OpenShift provides routes(or ingress in kubernetes) using NGINX/HA-Proxy(depending on your setup).

In this situation, I have used the following solution:


Disable Namespace Ownership Check in Router

You need to patch the router in OpenShift before starting any step(from OpenShift 3.9). By disabling Ownership check, you can allow a service to use a even if there is another service taking You can do it like this(from documentation):

oc adm router ... --disable-namespace-ownership-check=true

FYI: this also works in OKD as well.


I have set FORCE_SCRIPT_NAME in Usually I fetched the value from environment varibles, which I have set in the Deployment Config:

FORCE_SCRIPT_NAME = os.environ.get('DJANGO_FORCE_SCRIPT_NAME', '/subdirectory')  # without trailing slash

Using FORCE_SCRIPT_NAME will configure django’s url in path /subdirectory. But it is not sufficient to serve the django application in sub path, as SCRIPT_NAME in requests are not updated, also it will show some erratic behaviour such as showing double entry of /subpath in url, 404 Page not found issues etc. To fix this, lets go to the second step:


Lets update the file like this:

import os
from django.core.wsgi import get_wsgi_application
from django.conf import settings

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'dummy.settings')
_application = get_wsgi_application()

# Here is the important part
def application(environ, start_response):
    script_name = getattr(settings, 'FORCE_SCRIPT_NAME', None)
    if script_name:
        environ['SCRIPT_NAME'] = script_name
        path_info = environ['PATH_INFO']
        if path_info.startswith(script_name):
            environ['PATH_INFO'] = path_info[len(script_name):]

    scheme = environ.get('HTTP_X_SCHEME', '')
    if scheme:
        environ['wsgi.url_scheme'] = scheme

    return _application(environ, start_response)

In above code, we are getting the value of script_name from FORCE_SCRIPT_NAME, then putting that value in wsgi environ(environment variable).

Big thanks to

I got the implementation idea from this stackoverflow answer. Big thanks to @whp.

That is it for today, hope it helps. If you have a better approach to resolve this problem please make a comment in comment section below.

Last updated: May 27, 2020

  • x1


Share Your Thoughts
M ↓   Markdown