Deploy a Django Website to A2 Hosting with cPanel

How to Deploy a Django Website to a2hosting.com

Creating a Django website or application is fun. It is even more fun to publish your website to the internet and see the first visitors coming to your site.

In this tutorial I will show you how you can easily host a Django website on a2hosting.com. I chose A2Hosting since it is has been voted as one of the best Django hosting options. A2Hosting provides an inexpensive shared hosting plan and offers an anytime money back guarantee if you do not like their service. I tried their money back guarantee when I accidentally booked the wrong hosting plan. It works.

An example of a website which I created and is hosted on a shared web hosting solution of a2hosting.com is stocktimemachine.com.

But now let’s get started!

Create an a2hosting account

At first you need to sign up for a shared hosting solution on a2hosting.com. I chose the SWIFT plan since it offers unlimited websites, database, storage and data transfer.

When you chose a hosting plan A2 Hosting will ask you to choose a domain. You have several options:

  • Register a new domain. You can register a new domain which will be added to your hosting plan. You can choose any domain name if it is still available. This option currently costs $14,95 per year.
  • Transfer your domain from another registrar. If you already have a domain you can transfer it to A2 Hosting.
  • I will use my existing domain and updated my nameservers. If you already have a domain registered at another provider (e.g. at Namecheap or Domain Factory) you can also use this option and update your name servers at the other provider. This is what I did for stocktimemachine.com. I will show you how to do this in another post.
  • Use a subdomain from A2 Hosting. If you want to spend as little money as possible this is the option for you. You can use a subdomain of a2hosted.com with no additional cost.
Choose a domain at a2hosting.com
Choose a domain at a2hosting.com

In the last step you can configure your hosting order. I chose the monthly billing cycle.

Configure a2hosting.com order
Configure a2hosting.com order

After you signed up for an account you can see the dashboard with the hosting package you chose.

Dashboard of a2hosting.com
Dashboard of a2hosting.com

The most important buttons you see in the picture above are cPanel Login and Account DetailsAccount Details provides an overview of your connection details including your website URL, the nameservers and the login credentials to the cPanel. The cPanel is the user interface to administer your website.

Create your first Django application

First, login to the cPanel using the credentials provided on the Account Details page.

Create Python application

In the cPanel search for “python” and click on Setup Python App.

Setup python app in cPanel on a2hosting.com
Setup python app in cPanel on a2hosting.com

A form will appear in which you can configure your python virtual environment. I use the Python version 3.6 since the Django FAQ recommends using Python 3 for the latest version of Django.

Configure new Python virtual environment on a2hosting.com cPanel
Configure new Python virtual environment on a2hosting.com cPanel

After you clicked on the Setup Button A2 Hosting will create the Python application for you.

Created Python virtual environment in cPanel
Created Python virtual environment in cPanel

Click on the URL displayed in the App URI column. You notice that a Hello World Python application was created. The browser will show

It works!

Python 3.6.6

Create FTP account

To understand what files and folders were created with the python virtual environment you need to create an FTP account. Navigate back to the cPanel and search for FTP Accounts. Setup an FTP account with your preferred username and password as follows:

Create FTP account in cPanel
Create FTP account in cPanel

After you created the FTP account connect to the server using your favorite FTP client. I use FileZilla.

Python application file structure

You will find the following files and folders which were automatically created when you setup the Python application.

stocktimemachine.com/                  
 ├── public/             
 ├── tmp/                
 └── passenger_wsgi.py

The public and tmp folder are currently empty. They can later be used for the static files (e.g. image and CSS files) and the media files of the Django website.

The passenger_wsgi.py file was created and currently serves the It works! page which we saw earlier. We will edit this file later in order to serve our Django application. Currently the file looks like this:

import os
import sys

sys.path.insert(0, os.path.dirname(__file__))

def application(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/plain')])
    message = 'It works!\n'
    version = 'Python %s\n' % sys.version.split()[0]
    response = '\n'.join([message, version])
    return [response.encode()]

Deploy the application

Now we are ready to deploy our first Django application. To deploy a Django website we need to create one first. A good explanation can be found on the official Django website in Writing your first Django app. For this step you only have to do the part 1 of the tutorial.

You should now have a folder structure on your local machine which looks like this

project_name/                  
 ├── app_name/
 |   ├── migrations/
 |   ├── admin.py
 |   ├── apps.py
 |   ├── models.py
 |   ├── tests.py
 |   ├── admin.py
 |   ├── urls.py
 |   └── views.py            
 ├── project_name/ 
 |   ├── settings.py
 |   ├── urls.py
 |   └── wsgi.py 
 ├── db.sqllite3        
 └── manage.py

You now should have a local running Django application. In order to be able to deploy it to A2 Hosting we need to make some changes.

Upload your Django website

First upload your local files to the shared hosting platform via the FTP account that you created. The folder/file structure should look similar to this once everything is uploaded:

stocktimemachine.com/                 
 ├── app_name/
 |   ├── migrations/
 |   ├── admin.py
 |   ├── apps.py
 |   ├── models.py
 |   ├── tests.py
 |   ├── admin.py
 |   ├── urls.py
 |   └── views.py            
 ├── project_name/ 
 |   ├── settings.py
 |   ├── urls.py
 |   └── wsgi.py 
 ├── public/ 
 ├── tmp/ 
 ├── passenger_wsgy.py 
 ├── db.sqllite3       
 └── manage.py

Update passenger_wsgi.py

The next step is to update the passenger_wsgy.py on the a2hosting.com shared server such that your Django website is served. The passenger_wsgy.py file will currently look like:

import os
import sys

sys.path.insert(0, os.path.dirname(__file__))

def application(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/plain')])
    message = 'It works!\n'
    version = 'Python %s\n' % sys.version.split()[0]
    response = '\n'.join([message, version])
    return [response.encode()]

Update the file and replace the old code with the following

import os
import sys

# set variables
sys.path.append(os.getcwd())
os.environ['DJANGO_SETTINGS_MODULE'] = 'project_name.settings'

#setup django application
import django.core.handlers.wsgi
from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()

This tells the server to serve your Django website instead of the It works! message.

You need to update the project_name in line 6 to the name of your project.

Install Django on the server

Before your website will show anything you need to install Django on you server first. What you did on your local machine by using the command pip install django can be done directly in the cPanel. Go to your python application in the cPanel and in the row modules select the current Django version. Click the add button to install it.

Install Django in cPanel in a2hosting.com
Install Django in cPanel

After Django is installed on the server it will look like this. For the installation to take effect click the Update button.

Django installed in cPanel
Django installed in cPanel

Update settings.py

Before you can see anything you need to edit the settings.py file. Set the ALLOWED_HOSTS variable to your domain name or a wildcard as seen below. When your website is in productive mode you should not use a wildcard!

ALLOWED_HOSTS = ['*']

Go to the cPanel and restart your Python application. You should now see your Django website work 🙂

Django successfully installed on a2hosting.com
Django successfully installed on a2hosting.com

Fixing the POST issue

When you now try to login to your admin area you will see the following error:

Django admin login error
Django admin login error

This is due to the fact that the e SCRIPT_NAME in the passenger_wsgy.py file is set to a relative path instead of the root of the application. But don’t worry there is a workaround for this. You just have to update the passenger_wsgy.py file to the following (as before you need to update the project_name in line 5 to the name of your project):

import os
import sys
# Set up paths and environment variables
sys.path.append(os.getcwd())
os.environ['DJANGO_SETTINGS_MODULE'] = 'project_name.settings'

import django.core.handlers.wsgi
from django.core.wsgi import get_wsgi_application

SCRIPT_NAME = os.getcwd()

class PassengerPathInfoFix(object):
    def __init__(self, app):
        self.app = app

    def __call__(self, environ, start_response):
        from urllib.parse import unquote
        environ['SCRIPT_NAME'] = SCRIPT_NAME

        request_uri = unquote(environ['REQUEST_URI'])
        script_name = unquote(environ.get('SCRIPT_NAME', ''))
        offset = request_uri.startswith(script_name) and len(environ['SCRIPT_NAME']) or 0
        environ['PATH_INFO'] = request_uri[offset:].split('?', 1)[0]
        return self.app(environ, start_response)

application = get_wsgi_application()
application = PassengerPathInfoFix(application)

Now you can login to the Django admin page as before on you local machine.

I hope you enjoyed this tutorial. I if you have any questions just leave a comment below.