Deploying a Django Web App with PythonAnywhere

Video thumbnail

PythonAnywhere is simply a service we also have available for hosting Python Web projects. It's that simple. There's a free plan (I think for just one application) and also, obviously, a paid plan because they have to make a living somehow.

Account Creation

In this case, I'm already logged in. To create an account, and I'm not going to insult your intelligence, just follow the link below:

https://www.pythonanywhere.com

To access PythonAnywhere on Google, click the first link, login. If you don't have an account, create one, verify it, and you'll have access to a panel like this. It's that simple.

Project to upload

The project we're going to upload will be in Python, that is, in Django Python Web. Here we have a couple of options:

  • Console, which I think is the most interesting option, since we can use Git with all the advantages it brings and then update the project using a Git pull.
  • Files, which consists of creating a compressed file, uploading it, and that's it.

The console version requires a git push and everything else. And since I always use GitHub, I already have it.

Before uploading/cloning

Regardless of which option you choose, in your settings.py make sure to:

DEBUG = False
ALLOWED_HOSTS = ['tu_usuario.pythonanywhere.com']

Remember to have your requirements.txt file ready and updated.

Also, add references to your static folders:

Open your settings.py and add (or edit) the path for STATIC_ROOT:

import os
# Carpeta donde se guardarán los archivos estáticos recopilados
STATIC_ROOT = os.path.join(BASE_DIR, "staticfiles")
# Asegúrate de tener tu carpeta STATICFILES_DIRS si tienes otros archivos estáticos
STATICFILES_DIRS = [
   os.path.join(BASE_DIR, "static"),

Git repository

I'm going to use my repository, although obviously it would be your project here. It has to be public, at least temporarily, to clone. If you don't want to make it public, you can use the zip option. I'll make it public for a moment, copy the link, and clone from the PythonAnywhere console:

$ git clone https://github.com/tuusuario/<repo>.git

Creating the virtual environment, dependencies, migrations, and static files

The next step is to create the virtual environment with the corresponding command, specifying the Python version and the environment name. Important: You must have your requirements.txt ready to install dependencies. If you don't have one, you can easily generate it with a command.

From the console in PythonAnywhere, create a virtual environment.

$ mkvirtualenv --python=/usr/bin/python3.10 myenv

Or just put python3

$ mkvirtualenv --python=/usr/bin/python3 myenv

It should be automatically active, but if it is not activated:

$ workon myenv

Once the project is cloned, we install with:

$ pip install -r requirements.txt

Run the migrations and copy all static files (CSS, JS, images, etc.) from each app in your Django project into a single central folder (STATIC_ROOT) ready for the web server to serve in production:

$ python manage.py migrate
$ python manage.py collectstatic

Next, we configure the static files. We create the folder, define its path in the configuration, and serve them.

Creating the application in PythonAnywhere

In the dashboard, we create a new application manually (not with the Django wizard, because we already have the project). We select WSGI, which is the interface between the server and our Django application.

WSGI Configuration

Here we modify the project and virtual environment path. I recommend saving a copy of the original file before modifying it, in case something goes wrong. All I did was enter my project name, and it automatically took over the settings.

HTTPS and Additional Settings

We can force HTTPS and adjust static file paths. These details depend on each project. Additionally, from the PythonAnywhere Bash console, you can run all the usual commands such as migrate, collectstatic, etc.

Also, remember to configure the virtual environment folder that is requested from the aforementioned panel.

Finally, the most important step is to configure the WSGI file. Remember, this file.

WSGI is a file that tells a WSGI server (such as Gunicorn, uWSGI, or PythonAnywhere) how to load your Django app.

PythonAnywhere generates a file like this:

import os
import sys

# add your project directory to the sys.path
project_home = '/home/<youruser>/<yourproyect>'
if project_home not in sys.path:
    sys.path.insert(0, project_home)

# set environment variable to tell django where your settings.py is
os.environ['DJANGO_SETTINGS_MODULE'] = '<yourproyect>.settings'

# serve django via WSGI
from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()

Before editing it, the reader is advised to copy and paste the ORIGINAL, UNEDITED content into a file in the project—for example, in the root—which should look something like:

PythonAnywhereoriginal.py

This means that if you make a mistake, you can replace the content with the original.

Then, the only thing you should change is the name of the cloned project folder, which is usually the name of the folder cloned by Git:

project_home = '/home/acy29/django-shopping'

From the same web section, at the top, there's a "Reload" button that reloads your app. If all goes well, you should be able to access your application in production.

With this, we now have the Django application deployed to PythonAnywhere. In my case, the project is already running (no data yet, as that's separate).

Conclusion

With this, we now have the Django application deployed in PythonAnywhere. In my case, the project is already running (no details yet, as that's separate).

It's a fairly simple process: clone the repository, create the virtual environment, install dependencies, configure static files, and edit the WSGI file.
If you want to learn programming properly, remember that you can find my academy app with paid and free resources, as well as the description of all the commands.

I agree to receive announcements of interest about this Blog.

We show how to deploy a Django project to PythonAnywhere using Git and bash.

| 👤 Andrés Cruz

🇪🇸 En español