Deploy Django App in Sub Directory Using OpenShift
Apr 24, 2019 · 2 Min Read · 2 Likes · 0 CommentWhen 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 example.com/dummy. 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 xyz.com/abc
even if there is another service taking xyz.com
. You can do it like this(from documentation
):
oc adm router ... --disable-namespace-ownership-check=true
oc env dc/router ROUTER_DISABLE_NAMESPACE_OWNERSHIP_CHECK=true
FYI: this also works in OKD as well.
Set FORCE_SCRIPT_NAME
I have set FORCE_SCRIPT_NAME in settings.py
. 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:
Update wsgi.py
Lets update the wsgi.py
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 Stack Overflow 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: Jul 13, 2024
I won't spam you. Unsubscribe at any time.