Host your Django web-app on PythonAnywhere!
Tags: django, python, webdev, html
Published: 2023-08-10 10:27:22

Here’s how to host a Django web-app on PythonAnywhere _for free_, which is pretty sweet if you ask me! In this ”guide”, I’m going to be using [my portfolio/about me website](https://kureal.pythonanywhere.com/home/) as an example. You can find the source code [here](https://github.com/kurealnum/personal-website). 

## Creating the web-app itself 👨‍💻

First, you’ll need a fully functioning Django web-app (you won’t need to set up anything for production in Django though!). Next, you’ll also need to have your project on Github, and finally, make sure you have a `requirements.txt` file in your project. You can create this with `pip freeze > requirements.txt`.

Side note: You might be wondering why I’m using Django for a seemingly static website. I used Django because I chose to dynamically update my repositories using the [Github REST API](https://docs.github.com/en/rest). I’d also like to add a blogging section at some point, so naturally, Django will help with that.

Alrighty, let’s get into it!

## Starting with PythonAnywhere 🐍

Initially, you’ll want to make an account on [PythonAnywhere](https://www.pythonanywhere.com). Once you create an account, you’ll be shown a basic dashboard. Click on “New Console”, create a new Bash console, and clone your project. 

Then, create a virtual environment, and install Django and any other dependencies with `pip install -r requirements.txt`. 

**_Important Note:_** Take note of the python version used to create the virtual environment. You’ll need that later!

Now, navigate back to the dashboard, and then to the `Web` tab. From there, create a new web-app, and choose the `Manual Configuration` option (not the Django option), and the version of python you used to create your virtual environment.

## PythonAnywhere's file structure 📂

Before we go any further, I want to explain the file structure of PythonAnywhere. Initially, it was _very_ confusing for me, so hopefully I can help you to avoid the struggle of trying to figure it out on your own!

If you navigate to the `Files` tab from the dashboard, you’ll see a list of directories. At this point in time, you _should_ see a file structure that looks something like this:

- _.cache/_
- _.local/_
- _.virtualenvs/_
- _MyDjangoWebApp/_
- _MyVirtualEnv/_

Of course, `MyDjangoWebApp` and `MyVirtualEnv` will be called something else, but you get the point. By the way, all of these directories are subdirectories of `home/MyUserName`. 

Contrary to what you may think, we actually don’t need to touch `.cache`, `.local`, or `.virtualenvs`! Those are just directories generated by PythonAnywhere. For what it’s worth, I would just completely ignore these directories for the rest of the setup. The only directories that we’ll be interacting with are the ones that you added, `MyDjangoWebApp`, and `MyVirtualEnv`. 

## More setup with PythonAnywhere 🔎

Now that you (hopefully) understand the file system a little bit more, we can continue. Once you’ve set up your web app, enter the name and path of the virtual environment in the `Virtualenv` section of the `Web` tab. You can also optionally enter the path to your code in the `Code` section.

## WSGI file configuration 📄

After that, we’re going to edit our WSGI file. This is where it gets a little bit tricky. You won’t be editing your project's WSGI file, you’ll be editing PythonAnywhere’s. Go to the “Code” section, find the path to the WSGI configuration file, and open it.

Once you’re there, there’s going to be a lot of comments all over the place. You can delete everything except for the Django section. Now, make sure you uncomment everything in the Django section. It should look something like this when you’re done: 

```py
#+++++++++++ DJANGO +++++++++++
import os
import sys

# assuming your django settings file is at '/home/MyUserName/mysite/mysite/settings.py'
# and your manage.py is is at '/home/MyUserName/mysite/manage.py'
path = '/home/MyUserName/TOBECOMPLETED_1'
if path not in sys.path:
    sys.path.append(path)

os.environ['DJANGO_SETTINGS_MODULE'] = TOBECOMPLETED_2.settings'

# then:
from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()
```

Now that I’ve properly confused you, let me explain. `TOBECOMPLETED_1` should be replaced with your root project's name. `TOBECOMPLETED_2` should be replaced not with your project’s name, but with the actual project directory inside your root project’s name.

If that sounds a little bit puzzling, let’s use [my repository](https://github.com/kurealnum/personal-website) as an example. For instance, `TOBECOMPLETED_1` would be set as `personal-website`, and `TOBECOMPLETED_2` would be set as `personal_website`. Once you have this set up, make sure you save your file (top right), and make your way back to the `Web` tab.

## Finishing the PythonAnywhere setup 👩‍🏭

You’re almost done! The last thing to do is set up your database (if you’re using one). While I haven’t set up one myself, here’s what PythonAnywhere says to do:

> If, like most sites, your site uses a database, you'll need to set that up. Go to the `Consoles` tab, start a bash console, use cd to navigate to the directory where your Django project's manage.py lives, then run `./manage.py migrate”.

Now, return to the `Web` tab, and go to your web-app. Click the green `Reload site` icon. You should be up and running now! One last thing though, if you’re getting any errors or your site won’t load, check the log files!

## Closing 🚪

I hope this little guide helped you set up your first Django web-app on PythonAnywhere! Feel free to check out my web-app hosted on PythonAnywhere: https://kureal.pythonanywhere.com/home/

If I made any mistakes, or you have any ideas/comments, please feel free to leave a comment!

Contact me: 
- oscar.gaske.cs@gmail.com
- https://github.com/kurealnum