Configuring Django with Apache on a Raspberry Pi

Deb has another job for me to do around the house.
She would like to have a means of looking up which Films/TV Series we have lying around on Blu-Ray or DVD so she can save time looking for films we haven’t actually got. Just to be clear, she doesn’t mind hunting around for the disc in question, she just wants to make sure that it’s somewhere to be found in the first place.
She wants to be able to do this on any device at any time (let’s face it, there’s even a browser on your telly these days).
As DIY jobs go, this is a long way from being the worst as far as I’m concerned. After all, this time I should be able to put something together without the potential for carnage that’s usually attendant when I reach for the toolbox.

I happen to have a Raspberry Pi lying around which should serve as the perfect hardware platform for this sort of low traffic, low data-volume application.
The Pi is running Raspbian Jessie.
Therefore, Python is the obvious choice of programming language to use. By extension therefore, Django appears to be a rather appropriate framework.
In order to store the details of each movie we have, we’ll need a database. Django uses with Sqlite as the default.

We’ll also need an HTTP server. Whilst Django has it’s own built-in “development” server for playing around with, the favoured production http server appears to be Apache.

Now, getting Django and Apache to talk to each other seems to get a bit fiddly in places so what follows is a description of the steps I took to get this working…leaving out all the bits where I hammered my thumb…

Other places you may want to look

There are lots of good resources for Django out there.
The Django Project has a a list of Django Tutorials.
One particularly good beginners tutorial, especially if you have little or no experience of programming, is the Django Girls Tutorial.

Making sure that Raspbian is up-to-date

Before we start installing the bits we need, it’s probably a good idea to make sure that the OS on the Pi is up-to-date.
Therefore, open a Terminal Window on the Pi and run the following two commands…

sudo apt-get update -y
sudo apt-get upgrade -y

This may take a while, depending on how up-to-date your system is.
Once these commands have completed, you’ll probably want to make sure you haven’t got any unwanted packages lying around. To achieve this, simply run :

sudo apt-get autoremove

Python Virtual Environments

Look, don’t panic. This isn’t the sort of Virtual Environment that requires hypervisors and Virtual Machines and all that other complicated gubbins. We’re running on a Pi, after all, we really haven’t got the system resources to expend on that sort of nonsense.
A Python virtual environment is simply a way of “insulating” your application’s Python dependencies from those of any other applications you have/are/will/may develop/run on the same physical machine.

Getting this up and running is fairly simple, but first, just as a sanity check, let’s make sure that we have Python 3 installed and available :

python3 --version


Provided all is well, then next step is to install the appropriate Python 3 package for creating and running Virtual Environments so…

sudo pip3 install virtualenv

Next, we need to create a parent directory for our application. I’m going to create this under the home directory of the pi user that I’m connected as on the pi.
I’m going to call this directory “dvds” because I want to keep the name nice and short.
To create a directory under your home in Linux…

mkdir ~/dvds

You can confirm that the directory has been created in the expected location by running …

ls -ld ~/dvds

drwxr-xr-x 5 pi pi 4096 Feb 14 13:05 /home/pi/dvds


cd ~/dvds
virtualenv dvdsenv

…will create the python executables referenced in this environment :


Notice that this has created a directory structure under a new directory called dvdsenv :


Now start the virtualenv and note what happens to the prompt :

source dvdsenv/bin/activate


One small but welcome advantage to running in your new environment is that you don’t have to remember the “3” whenever you want to run python. The easiest way to demonstrate this is to stop the virtual environment, get the python version, then re-start the virtual environment and check again, like this…


Installing Django

We want to do this in our newly created virtual environment.
So, if you’re not already in it, start it up :

cd ~/dvds
source dvdsenv/bin/activate

Now we use pip3 to get django. NOTE – as with the python command, we don’t need to remember the “3” for pip inside the virtual environment…

pip install django


Still in the Virtual environment, we can now create our new django project ( be sure to be in the dvds directory we created earlier) :

cd ~/dvds startproject dvds .

Note the “.” at the end of this command. that means that the directory tree structure of the new application should be created in the current directory.

Once this has run, you should see a sub-directory called dvds :


We now need to make some changes to some of the files that Django has created in this directory. To make these changes I’m going to use the default Raspbian graphical editor, Leafpad. If you’d prefer something like nano, then knock yourself out. Just replace “leafpad” with the executable name of your editor in the commands that follow…

leafpad ~/dvds/dvds/

We need to make a couple of changes to this file.
Firstly, in the INSTALLED_APPS section of the file (around about line 33) we want to add our application – dvds. After the change, this particular section of the file should look something like this :


The other thing to do is to make sure that STATIC_ROOT has been defined. If this does not already exist in then add it at the end of the file :

STATIC_ROOT = os.path.join( BASE_DIR, "static/")

To get Django to accept these changes we need to migrate them. Note that we need to do this from inside the virtual environment so start it if it’s not already running…

cd ~/dvds
source dvdsenv/bin/activate
./ makemigrations
./ migrate


Before we finally get Django up and running, we need to setup the default admin UI.
To do this, we first need to create an admin user :

./ createsuperuser


…then setup the static files used by the admin app…

./ collectstatic

You have requested to collect static files at the destination
location as specified in your settings:


This will overwrite existing files!
Are you sure you want to do this?

Type 'yes' to continue, or 'no' to cancel:

Type “yes” and you’ll get …

Copying '/home/pi/dvds/dvdsenv/lib/python3.4/site-packages/django/contrib/admin/static/admin/css/base.css'
Copying '/home/pi/dvds/dvdsenv/lib/python3.4/site-packages/django/contrib/admin/static/admin/css/widgets.css'
Copying '/home/pi/dvds/dvdsenv/lib/python3.4/site-packages/django/contrib/admin/static/admin/css/rtl.css'
Copying '/home/pi/dvds/dvdsenv/lib/python3.4/site-packages/django/contrib/admin/static/admin/js/admin/RelatedObjectLookups.js'

61 static files copied to '/home/pi/dvds/static'.

Now we can test that everything is working as expected by running Django’s own “development” http server :

./ runserver


If we now point the Epiphany browser on the pi to that address, we should see the default Django page :


Better even than that, if you append “/admin” to the url – i.e.

You should see…


Using the username and password you just created for with the “createsuperuser” command just now, you should get access to :


Installing Apache

This is fairly straight forward, to start with at least.
First of all, you don’t need to be in the Python Virtual Environment for this so, if you are then deactivate it :


Once this command has completed, the prompt should now return to normal.

I’ll be sure to tell you when you need the Virtual Environment again.

To install Apache…

sudo apt-get install apache2 -y

Once that’s completed, you should be able to confirm that Apache is up and running simply by pointing your browser to :


…which should display the Apache Default Page :


In addition to Apache itself, we need some further packages to persuade Apache to serve pages from our Django application :

sudo apt-get install apache2-dev -y
sudo apt-get install apache2-mpm-worker -y
sudo apt-get install libapache2-mod-wsgi-py3 

Got all that ? Right…

Configuring Apache to serve Django Pages using WSGI

First of all, we need to tell Apache about our Django application. To do this we need to edit the 000-default.conf which can be found in the Apache directories :

leafpad /etc/apache2/sites-available/000-default.conf

We need to add some entries to the section of the file. Once we’re done, the entire file should look something like this :

	# The ServerName directive sets the request scheme, hostname and port that
	# the server uses to identify itself. This is used when creating
	# redirection URLs. In the context of virtual hosts, the ServerName
	# specifies what hostname must appear in the request's Host: header to
	# match this virtual host. For the default virtual host (this file) this
	# value is not decisive as it is used as a last resort host regardless.
	# However, you must set it for any further virtual host explicitly.

	ServerAdmin webmaster@localhost
	DocumentRoot /var/www/html

	# Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
	# error, crit, alert, emerg.
	# It is also possible to configure the loglevel for particular
	# modules, e.g.
	#LogLevel info ssl:warn

	ErrorLog ${APACHE_LOG_DIR}/error.log
	CustomLog ${APACHE_LOG_DIR}/access.log combined

	# For most configuration files from conf-available/, which are
	# enabled or disabled at a global level, it is possible to
	# include a line for only one particular virtual host. For example the
	# following line enables the CGI configuration for this host only
	# after it has been globally disabled with "a2disconf".
	#Include conf-available/serve-cgi-bin.conf

 Alias /static /home/pi/dvds/static
        Require all granted

            Require all granted

    WSGIDaemonProcess dvds python-path=/home/pi/dvds python-home=/home/pi/dvds/dvdsenv
    WSGIProcessGroup dvds
    WSGIScriptAlias / /home/pi/dvds/dvds/

# vim: syntax=apache ts=4 sw=4 sts=4 sr noet

Next, we need to make sure that Apache has access to the bits of Django it needs. To do this, we’ll give access to the group that the user under which Apache runs belongs to :

chmod g+w ~/dvds/db.sqlite3
chmod g+w ~/dvds
sudo chown :www-data db.sqlite3
sudo chown :www-data ~/dvds

After all of that, the “Apache” group (www-data) should be the group owner of the Virtual environment as well as our SQLITE database :


Finally, we need to re-start Apache for these changes to take effect :

sudo service apache2 restart

If we now go to the Apache url (http://localhost), we can see that it’s now showing the Django default page :

If you see that then, congratulations, it works !

Accessing Django from another computer on the network

The server name of my Raspberry Pi is raspberrypi. If you want to check that this is the case for you, simply open a Terminal on the pi and run :

uname -n

In order to access the application from other computers on my local network, I’ll need to add this server name to the ALLOWED_HOSTS list in the file of the application.

To do this :

leafpad ~/dvds/dvds/

Amend the ALLOWED_HOSTS entry from this :


…to this…


And you should now be able to access the Django application from a remote machine by using the url :


…like this…


Hopefully, this has all helped you to get up and running without hitting your thumb.

Finally, if you want to know what happens next in my Django adventures, you can see how the rest of the DVD library app pans out, then check out :

  1. setting up the database tables via Django
  2. the Controller and UI application layers

26 thoughts on “Configuring Django with Apache on a Raspberry Pi

  1. This was very well documented and a breeze to follow – I was up and running in almost no time at all. Well done sir!

  2. Hey Mike, I recently setup my own web server using a different guide that basically only required configuring Apache (although PHP and MySQL were installed). I’m thinking about scratching it and starting out with your guide here since I’m more familiar with Python, although totally new to Django — one question: how does SQLite play into the mix here?

    Is that a database you’d previously written?

    These four lines:

    chmod g+w ~/dvds/db.sqlite3
    chmod g+w ~/dvds
    sudo chown :www-data db.sqlite3
    sudo chown :www-data ~/dvds

    Nice guide btw!

  3. Hey Mike,
    thanks a lot for the tutorial! I don’t think I would’ve been able to set this up myself in any reasonable time.
    One thing though: It seems that “sudo apt-get install apache2-mpm-worker -y” does not work any more. At least not on the current os my Pi is running on. Anyway after a bit of googling I found a solution and thought it might be worth sharing.
    So apparently the MPMs are being installed together with Apache and you then just need to configure which one to use.
    “To determine which MPM is currently in use, run apache2ctl -V. You will see a line such as:

    Server MPM: prefork
    Assuming that you are running “prefork” (as in the above example), the switch is made with the following commands:

    a2dismod mpm_prefork
    a2enmod mpm_worker
    service apache2 restart”

    I hope this might help some others having the same issue I did.


  4. Hi Mike, many thanks for sharing your tutorial really helpful. I seem to be having trouble on last starting block with getting apache2 to serve up django files. I previously set up a basic wordpress installation just as a blog to record what i’ve been doing coding wise locally on the pi and mysql as well (having used both a lot in live web environments).

    Giving django a go so following guide and not quite sure what i’ve done wrong as your guide helped get django to work with virtual env but I’m getting error saying nothing found on /localhost/ (it is serving a web error from apache2) so not quite sure why!

    Is there any debugging i can run from apache2 to check if it’s running the virtual environment and django?

    • Tim,

      I guess I’d start by checking the logs for Apache which are usually found in


      Just out of interest, what is the error that you are getting from Apache ?



  5. Thanks for this! Really!

    I noted a few things:
    – You need to have installed samba in order to access the raspberry pi using its hostname. Otherwise, you’ll have to access it using it’s IP address (from another computer)
    – To use the GPIO pins, you have to add www-data to the ‘gpio’ and ‘kmem’ user groups

    I also found that you have to be the root user to edit the apache configuration file.

  6. Hi Mike,
    Thanks a lot for this tutorial. I am having an issue with displaying the 000-default.conf file, as I see it in the tutorial there seems to be missing some lines?

    Hope you can help me out 🙂


    • Floris,

      I’m not sure if I understand you correctly so apologies if this is the case.
      The lines that are highlighted are the ones I’ve added to this file. They are not there by default.



  7. I have the same issue. It’s a guess, but it looks like lines resembling a html ‘tag’ aren’t displayed in your file above. Other examples of apache 000-default.conf files I found have the file content wrapped in ‘VirtualHost’ tags (which aren’t shown above for me) and both ‘Require all granted’ lines appear to be floating in space when other examples have them wrapped in ‘Directory’ tags (again not shown above for me). I’m not sure exactly what’s supposed to be there (that’s why I’m here!), but I suspect there’s something wrong with the way file is displayed (on Chrome and Safari).

    The rest has been very easy to follow though, thanks!

    • Dave,
      It seems to be displaying ok as far as I can see.
      I don’t have that particular pi up and running at the moment so I’m not able to check directly against the original file. However, I’ve checked the source of the post and the file does appear to be faithfully reproduced.
      I’ve removed any formatting from WordPress, just in case.


  8. Hi Mike,

    Thanks for a great article – was extremely helpful. But just to let you know I’m having exactly the same problems as Dave and Floris – your example of what should be in the 000-default.conf file is not displaying all information correctly (I’m using Chrome).

    Apart from that minor glitch I’ve found this a really good guide. Thank you.

  9. Hi Mike,

    Thanks for the simple step-by-step – worked a treat – with a couple of side-tracks which have already been mentioned above.

    I also cannot see the tags which Dave, Floris & James (previous 3 commenters) have mentioned.

    the conf file is missing all
    I’ve taken a screenshot of how it appears to me so you can see what we are seeing:

    I don’t know if wordpress will like me putting a link in here, so in case it get’s damaged by wordpress put this back together:
    https colon slash slash www dot dropbox dot com slash s slash kng4gde358fgmsv slash conf dot png?dl=0
    I have got it working for now by just commenting out the two Require all granted lines.

    Thanks again for the well written walk-through.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.