In my last post I finally officially introduced mod_wsgi-express, an extension to mod_wsgi that I have been working on over the past year and a half. The purpose of mod_wsgi-express is to radically simplify the steps required to deploy a Python WSGI application using Apache and mod_wsgi. In that post I introduced some of the basic functionality of mod_wsgi-express. As Django is the most popular Python web framework, in this post I want to explain what is involved in using mod_wsgi-express with Django.
The structure of a Django project
When starting a new Django project the ‘startproject’ command is supplied to the ‘django-admin’ script to create the initial project structure. The directories and files created in the directory where the command is run is:
The immediate subdirectory created below where the ‘startproject’ command was run, and which contains the ‘manage.py’ script, is referred to as the base directory. The name of the base directory is whatever you called the name of your project.
The ‘manage.py’ file contained in the base directory is a site specific variant of the ‘django-admin’ script, which provides a means of executing various builtin Django admin commands against your site, as well as any admin commands which may later be added to the site by associating add-on applications with it.
In addition to the ‘manage.py’ script a further subdirectory, with the same name as the base directory, will have been created. This directory will contain the actual code for your site. Worth noting is that this directory actually contains an ‘__init__.py’ file. This is important as it actually marks the directory as a Python package, rather than just a collection of Python modules.
This directory also contains two other files which are important and come into play when aiming to deploy your site. These are the ‘settings.py’ file, which is used to customise the capabilities of your site and how it may be made available, plus the ‘wsgi.py’ file, which contains the WSGI application entry point which any WSGI server needs to know about. It is the function or other callable object specified as the WSGI application entry point to which the details of each request received by the WSGI server will be passed to have your Django application serve the request.
As far as now using mod_wsgi-express with such a Django project, there are two main things that mod_wsgi-express needs to be told. These are the location of the base directory and the full name of the module containing the WSGI application entry point.
The location of the base directory is important because it is the parent directory for the Python package containing the code for your site. This directory will need to be added to the Python module search path so the Python package containing your site code can be found. In particular we need it to be able to find the ‘wsgi.py’ file when referring to it via its full module name.
So if we were still located in the top level directory where the ‘startproject’ command was run, one above the base directory, we would run ‘mod_wsgi-express’ as:
mod_wsgi-express start-server --working-directory mysite --application-type module mysite.wsgi
If we had instead run mod_wsgi-express inside of the base directory, we could have used just:
mod_wsgi-express start-server --application-type module mysite.wsgi
The later still works because the working directory will be set to be the current directory if none is explicitly supplied.
To have such styling applied for the ‘/admin’ URL, we also need to tell mod_wsgi-express about the location of any static media files and at what sub URL they need to be made available so that they can be found by any HTTP client.
Hosting of static media files
When using Django’s own builtin development server, it will automatically make available any static media files at the required sub URL. When you use a separate WSGI server however, that automatic mapping and hosting of the static media files will not occur.
It is possible to configure Django to host these static media files itself even in a production setting, but this is sub optimal and not recommended. Instead such static media files should be hosted by a proper web server.
In the case of mod_wsgi-express, because it is actually using Apache underneath, then we already have a true web server available which can be used to host the static media files in a production setting.
Before we can make use of that capability though, we first need to setup the Django project to allow us to easily collect together all the static media files together in the one location. This is necessary as normally such static media files are spread out across different locations, including as part of Django itself, or any installed add-on applications.
The first thing we therefore need to do is modify the ‘settings.py’ file and add the setting:
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
This is best placed at the end of the ‘settings.py’ file immediately after the existing setting for ‘STATIC_URL’.
What the ‘STATIC_ROOT’ setting does is say that all static media files are to be placed into a directory called ‘static’ located within the base directory.
To actually get the files copied into that location we now need to run:
python manage.py collectstatic
Note that although we run this initially, this command must be run every time any update is made to static media files located within any add-on applications, or were Django itself updated to a newer version
After having run this command, this will now leave us with:
So the ‘static’ subdirectory has been created, with a further subdirectory containing the static media files for the admin component of Django implementing the ‘/admin’ sub URL.
Now running mod_wsgi-express from within the base directory we would use:
mod_wsgi-express start-server --url-alias /static static --application-type module mysite.wsgi
The new option in this command is ‘—url-alias’. This option takes two arguments. The first is the sub URL where the static media files are to be made available. This should match the value which the ‘STATIC_URL’ setting had been set to. The second argument is the location of the directory where the static media files were copied. As we are running this command in the base directory and the location of the static media files is an immediate subdirectory, we can specify this as just the name of the subdirectory.
We should now have a working Django site using Apache/mod_wsgi. We have though had to duplicate certain information on the command line which is actually available in the Django settings file. The next step therefore is to eliminate that requirement by integrating mod_wsgi-express into the Django site itself as a Django admin management command. I will cover how that is done in the next blog post about this topic.