Upgrading to Django 1.11 and Python 3

I thought swapping to Python 3 would be very painful, I couldn't have been more wrong.

  • 13 Aug 2017
  • Matthew Wittering

Recently I decided it was probably worth upgrading to version 1.11 of Django from 1.10 and thought that it was high time that I moved unto version 3 of Python. There had been any practical reason for delaying expect the work follow and my focus on writing features had been entirely centred around Python 2.7.

As I'm experimenting with more and more third party Django components - I believed more and more it made sense to make the swap.

The swap was very simple. For me it was a case of running the tests and fixing as required and running all my management commands to verify everything works as expected.

The hardest part was swapping over from using __unicode__ and unicode() to __str__ and str() respectively and replacing iteritems() with items().

For deployment it was only a little more complicated. Before I did my git pull origin master to load my latest changes setup a new virtual environment for Python to install Python 3.4 and the required modules.

virtualenv -p python3 env3

Next I used pip to install the Python models from the requirements file.

pip install -r requirements.txt

Now, the bit which I found out late during the deployment as I hadn't tested before hand. It was necessary for me to replace the mod_wsgi module for Apache or HTTPD in Fedora for the version need to execute Python 3 code. All the tutorial I've previously read for deploying Django projects seem to assume you're using Python 2.7. This isn't too surprising as the default version is Python 2.7.13 on my Fedora 26 machine.

Start by uninstalling the previous version.

sudo dnf remove -y mod_wsgi

Then install the Python 3 equivalent.

sudo dnf install -y python3-mod_wsgi

Now all is required is to swap the virtualenv directory name in the VirtualHost config...

<VirtualHost *:80>
  ServerName www.example.com
  ServerAlias www.example.com
  Redirect / http://example.com/
<VirtualHost *:80>
  ServerName example.com
  ServerAlias example.com

  Alias /static /home/demo/website/static
  Alias /robots.txt /home/demo/website/static/robots.txt

  <Directory /home/demo/website/static>
      Require all granted

  <Directory /home/demo/website/website>
    <Files wsgi.py>
      Require all granted

  WSGIDaemonProcess website python-path=/home/demo/website:/home/demo/website/env3/lib/python2.7/site-packages
  WSGIProcessGroup website
  WSGIScriptAlias / /home/demo/website/website/wsgi.py

... and the restart of Apache to finish.

sudo systemctl restart httpd