Deploying a Django app with Apache + mod_wsgi (Windows)

Deepankar Acharyya
7 min readOct 5, 2020

--

Photo by Andrew Neel on Unsplash

As a part of my summer internship project, I was asked by my guide to build a Django dashboard app and deploy it using the Apache server. It was a simple enough task but while doing it, I had to search through a lot of websites to get the work done. But thanks to it, I got a taste of the deployment process.

So in order to save you all from the hard labor I endured, I decided to compose this article. But before diving into how to do it, let's ponder over some points first, to get our basics clear.

1. Why do we need another web-server?

Django has evolved to be one of the most popular and powerful web frameworks that help developers to quickly code python web apps. Django includes a simplified development server for testing and debugging the code locally. But for production purposes, it needs some extra help in order to serve the incoming requests efficiently and securely.

When we deploy a Django app, we use 2 different servers:

  • Front-end Server/Reverse Proxy: This kind of server relief python from handling trivial, but massive requests. These requests are usually to static files (these files can be pretty big). The front-end servers take care of such requests allowing the Django application to focus on other requests (related to the functionalities of the application). Also, Python doesn’t handle large files in concurrent environments well. The reverse proxy is pretty good at serving concurrent requests, it will act as the guard for the application, allowing only the necessary requests to reach the Django application. In our case, this role is fulfilled by the Apache Server.

Apache is a web server (written in C), that runs as a service on the host computer (ensuring that it keeps running in the background). This server takes care of the load-balancing and scaling for the deployed application.

To get a more objective idea on forward and reverse proxy, I would request you to kindly visit the following link:

  • WSGI Server:

“Since most web servers don’t natively speak Python, we need an interface to make that communication happen, comes to the rescue: the WSGI server.

This server handles the loading of the Django application and communicating with it properly. It handles the number of processes used by the application, and how many concurrent requests the application will be able to attend. It acts as an interface between the Front-end Server (Apache) and the Django application.

In our case, we have used mod_wsgi for implementing the WSGI server.

Just to clarify, WSGI is a standard interface specification for running Python web applications. Whereas mod_wsgi is a standard WSGI container (an implementation).

A WSGI server only receives the request from the client, passes it to the application and then sends the response returned by the application to the client. It does nothing else. All the gory details are supplied by the application.

2. What is mod_wsgi?

Django applications are WSGI (Web Server Gateway Interface) applications, i.e. we would need an application server in the first place to serve the application. WSGI (compliant) applications can be stacked. Those in the middle of the stack are called middleware and must implement both sides of the WSGI interface, application and server.

The whole concept of WSGI and Python Applications is beautifully explained in the following brief article by Juan Benito Pacheco Rubio:

Mod_WSGI is an Apache module implementing the WSGI specification. This module takes care of the implementation of the WSGI standard on the server-side. Whereas on the application side Django takes care of it. The mod_wsgi module embeds the python application (the Django app) within the server and allows communication via the Python WSGI interface.

To get a deeper understanding of the WSGI specifications, you can visit the following page:

Now before using it, we have to install the mod_wsgi module. This can be done by just executing the following pip command :

pip install mod-wsgi

3.Deploying the Django app with Apache

Now finally we came to the implementation part. Before we get started tweaking the settings, lets us first download the necessary files/software. Here I am going to deploy my Django dashboard app (with Amcharts, PostgreSQL Database, jQuery, JavaScript). I will not be discussing the specifics of the dashboard app, just about the changes that are required to be made in its files.

Step 1: Download the Apache Server

Go to the following website (link) and download the file (meeting your OS specs). This will download a zipped file. Once unzipped, the downloaded file will yield 1 folder (Apache24) and 2 additional files.

Step 2: Installing the Apache Server

Before installing, we need to move the unzipped folder (Apache24) to a new location. In C drive, create a folder named ‘apache24’ and copy the Apache24 folder from the unzipped folder to the new apache24 folder.

The next step is adding the apache folder to the system path (“C:\apache24\Apache24\bin”). Also add an environment variable (MOD_WSGI_APACHE_ROOT_DIR “C:\apache24\Apache24” ).

Adding to the Path and adding the system variable MOD_WSGI_APACHE_ROOT_DIR

Now we are ready to install the Apache server. Just launch the command prompt and run the following command:

httpd.exe -k install

Step 3: Configuring the WSGI settings

I have assumed that you already have the mod_wsgi module installed in your system/environment. Now run the following command:

mod_wsgi-express module-config

The output will be of the following form:

LoadFile “c:/users/myuser/appdata/local/programs/python/python37/python37.dll”

LoadModule wsgi_module “c:/users/myuser/appdata/local/programs/python/python37/lib/site-packages/mod_wsgi/serve

r/mod_wsgi.cp37-win_amd64.pyd

WSGIPythonHome “c:/users/myuser/appdata/local/programs/python/python37”

Copy this output to someplace safe, we will be needing it soon. (Let's call it reference point 1)

In the Django project folder, add a file: wsgi_windows.py and add the following lines of code:

import os

import sys

import site

from django.core.wsgi import get_wsgi_application

# Add the app’s directory to the PYTHONPATH

sys.path.append(‘C:/Users/myuser/Desktop/charts_django/dashboard/Census_Dashboard/dashboard’)

sys.path.append(‘C:/Users/myuser/Desktop/charts_django/dashboard/Census_Dashboard/dashboard/board’)

os.environ[‘DJANGO_SETTINGS_MODULE’] = ‘dashboard.settings’

os.environ.setdefault(‘DJANGO_SETTINGS_MODULE’, ‘dashboard.settings’)

application = get_wsgi_application()

Step 4: Editing the settings.py

Next in-order to link our Django app to the apache server, we need to first edit the content of the settings.py in our Django project folder. In the file, add/edit the following lines:

DEBUG = False

ALLOWED_HOSTS = [“localhost”,”*”,”127.0.0.1"]

WSGI_APPLICATION = ‘dashboard.wsgi_windows.application’

STATIC_URL = ‘/static/’

STATIC_ROOT=os.path.join(BASE_DIR, ‘static’)

After editing, run the following command:

python manage.py collectstatic

This will create the static folder in the Django project directory.

Step 5: Editing the Apache configuration

For configuring and linking the Apache server to out Django app, we need to edit 2 files.

Open the file ‘httpd.conf’ available at the location:

C: > apache24 > Apache24 > conf > httpd.conf

Append the output from reference point 1 (step 3) to it. Next, uncomment and add the following lines :

Define SRVROOT “c:/apache24/Apache24”

ServerName localhost

Include conf/extra/httpd-vhosts.conf

Next, we need to edit the httpd-vhosts.conf file available at location:

C: > apache24 > Apache24 > conf > extra > httpd-vhosts.conf

And add the following lines of code:

<VirtualHost *:80>

ServerName localhost

ServerAlias localhost

WSGIScriptAlias / “C:\Users\myuser\Desktop\charts_django\dashboard\Census_Dashboard\dashboard\dashboard\wsgi_windows.py”

ErrorLog “C:\Users\myuser\Desktop\charts_django\dashboard\Census_Dashboard\dashboard\dashboard\dashboard.error.log”

CustomLog “C:\Users\myuser\Desktop\charts_django\dashboard\Census_Dashboard\dashboard\dashboard\dashboard.access.log” combined

<Directory “C:\Users\myuser\Desktop\charts_django\dashboard\Census_Dashboard\dashboard\dashboard”>

<Files wsgi_windows.py>

Require all granted

</Files>

</Directory>

Alias /static “C:\Users\myuser\Desktop\charts_django\dashboard\Census_Dashboard\dashboard\static”

<Directory “C:\Users\myuser\Desktop\charts_django\dashboard\Census_Dashboard\dashboard\static”>

Require all granted

</Directory>

</VirtualHost>

The paths in the above lines of codes must be modified according to the location of the Django app in the system.

Step 6: Reload and watch it play

In order to load the latest changes, we need to reload the Apache server using the following command:

NOTE: Run the command prompt in administrator mode.

(to start the apache server, httpd.exe -k start)

httpd.exe -k restart

Finally, go to the website (in my case “localhost” ) and watch your app in action.

So that's how it is done.

Now but there are many other options in-place of Apache and mod_wsgi? Why choose this one?

Well yes if you search the web, you can find a number of different options with many different features. But I did my deployment using Apache and mod_wsgi just because I was asked to do it using that😶 .

--

--

Deepankar Acharyya

I am an engineer by profession and coder by religion. I like to explore different technologies and write about my technical experiences.