Deploying to PythonAnywhere manually
In the main tutorial, we deployed our app using PythonAnywhere's "autoconfigure" script, which did a lot of magic for us. In this extension we'll take a peek "behind the scenes" and find out what autoconfigure script actually did, by learning how to deploy our code manually to PythonAnywhere.
Why might you be interested in doing this? Beyond pure curiosity, the steps involved in a manual deployment are more or less the same steps you'd need to go through if you were trying to deploy to a different hosting provider, including running your own server, which is something you might want to do some day.
Running through the procedure manually is also a good idea for DjangoGirls coaches. If something goes wrong with the autoconfigure script in one of the workshops, knowing how to do it manually could help you get one of the attendees out of a broken state and back to a working deployment.
So, read on!
- This extension assumes you already have some code on GitHub. See the begining of the deploy chapter for instructions on that, if you need.
- It also assumes you have a PythonAnywhere account. If it already has a djangogirls webapp running in it, you'll need to delete that first (or just sign up for a new account!)
Deploying to PythonAnywhere, or indeed to any server, involves pretty much the same steps:
- Getting your code onto the server. We'll use
git pullfor this
- Installing your dependencies on the server. We'll use a virtualenv for this, just like on your own computer, but we'll use a shortcut recommended by PythonAnywhere called
- Configuring your database on the server. The database on your own computer and the one on the server are separate. We'll use
manage.py createsuperuserfor this.
- Configuring your static files on the server. On your own laptop,
runservertakes care of static files, but servers like to manage things differently in order to optimise serving static files. Here we'll use a new command called
collectstatic, and configure the static files through PythonAnywhere's Web tab.
- And actually hooking up our Django app to be served, live, on the public Internet. We do this on PythonAnywhere's Web tab, by configuring something they call a WSGI file.
Go to the PythonAnywhere Dashboard, and choose the option to start a "Bash" console – that's the PythonAnywhere version of a command-line, just like the one on your computer.
pointing at Other: Bash in Start a new Console
Note PythonAnywhere is based on Linux, so if you're on Windows, the console will look a little different from the one on your computer.
Let's pull down our code from GitHub and onto PythonAnywhere by creating a "clone" of our repo. Type the following into the console on PythonAnywhere:
$ git clone https://github.com/<your-github-username>/my-first-blog.git <your-pythonanywhere-username>.pythonanywhere.com
- Use your actual GitHub username in place of
- And use your actual PythonAnywhere username in place of
This will pull down a copy of your code onto PythonAnywhere, and put it into a folder named after your (future) website address. Check it out by typing
│ ├── __init__.py
│ ├── admin.py
│ ├── migrations
│ │ ├── 0001_initial.py
│ │ └── __init__.py
│ ├── models.py
│ ├── tests.py
│ └── views.py
Just like you did on your own computer, you need to create a virtualenv on PythonAnywhere. In the Bash console, type:
$ mkvirtualenv --python=python3.6 <your-pythonanywhere-username>.pythonanywhere.com
Running virtualenv with interpreter /usr/bin/python3.6
Installing setuptools, pip...done.
mkvirtualenvcomes from a tool called "virtualenvwrapper", which PythonAnywhere recommends. It's a set of shortcuts built around the normal
virtualenvcommand that you've already learned about using on your own computer.
When the command finishes, your virtualenv should be active; we've named it after your future website address, just like we named the project source code folder. Let's try de-activating and re-activating the virtualenv, just for practice.
deactivate, just like on your computer, but to activate we use the virtualenvwrapper shortcut command
workon, which just needs the name of your virtualenv:
(ola.pythonanywhere.com) $ deactivate
$ which python
$ workon <your-pythonanywhere-username>.pythonanywhere.com
(ola.pythonanywhere.com) $ which python
Now let's install Django into our virtualenv on PythonAnywhere
(ola.pythonanywhere.com) $ pip install 'django<2'
Successfully installed django-1.11.9
pip installstep can take a couple of minutes. Patience, patience! But if it takes more than five minutes, something is wrong. Ask your coach.
Here's another thing that's different between your own computer and the server: it uses a different database. So the user accounts and posts can be different on the server and on your computer.
Just as we did on your own computer, we repeat the step to initialize the database on the server, with
Go back to your Bash console, make sure your virtualenv is still active, and then run these commands. (If you've closed your console, you can open a new one, and use the
workoncommand to activate your virtualenv).
(ola.pythonanywhere.com) $ python manage.py migrate
Operations to perform:
Applying sessions.0001_initial... OK
(ola.pythonanywhere.com) $ python manage.py createsuperuser
Now we learn a new command,
collecstatic, whose job it is to collect all the static files from your apps (including apps you've written like blog, and built-in Django apps like the admin), and put them in one place, so the server can find them:
(ola.pythonanywhere.com) $ python manage.py collectstatic
You have requested to collect static files at the destination
Are you sure you want to do this?
62 static files copied to '/home/ola/ola.pythonanywhere.com/static'.
Now our code is on PythonAnywhere, our virtualenv is ready, and the database is initialized. We're ready to publish it as a web app!
Click back to the PythonAnywhere dashboard by clicking on its logo, and then click on the Web tab. Finally, hit Add a new web app.
After confirming your domain name, choose manual configuration (N.B. – not the "Django" option) in the dialog. Next choose Python 3.6, and click Next to finish the wizard.
Note Make sure you choose the "Manual configuration" option, not the "Django" one. We're too cool for the default PythonAnywhere Django setup. ;-)
You'll be taken to the PythonAnywhere config screen for your webapp, which is where you'll need to go whenever you want to make changes to the app on the server.
screenshot of web tab virtualenv config section with path correctly filled in
In the "Virtualenv" section, click the red text that says "Enter the path to a virtualenv", and enter
/home/<your-PythonAnywhere-username>/my-first-blog/myvenv/. Click the blue box with the checkmark to save the path before moving on.
Note Substitute your own PythonAnywhere username as appropriate. If you make a mistake, PythonAnywhere will show you a little warning.
We need to tell PythonAnywhere that static files which live under the URL
/static/are all located in a file inside your source code folder called static. We do that in the "Static Files" section on the Web tab.
Click the red text that says "Enter URL", and enter
/static/, and click the blue checkbox to save. Then click the text that says "Enter path", and enter
/home/<your-pythonanywhere-username>/<your-pythonanywhere-username.pythonanywhere.com/static(using your own username, as usual):
screenshot of web tab static files config section with url and path correctly filled in
Django works using the "WSGI protocol", a standard for serving websites using Python, which PythonAnywhere supports. The way we configure PythonAnywhere to recognize our Django blog is by editing a WSGI configuration file.
Click on the "WSGI configuration file" link (in the "Code" section near the top of the page – it'll be named something like
/var/www/<your-PythonAnywhere-username>_pythonanywhere_com_wsgi.py), and you'll be taken to an editor.
Delete all the contents and replace them with the following:
path = '/home/<your-pythonanywhere-username>/<your-pythonanywhere-username>.pythonanywhere.com')
if path not in sys.path:
os.environ['DJANGO_SETTINGS_MODULE'] = 'mysite.settings'
from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()
Note As always, substitute your own PythonAnywhere username in this file.
This file's job is to tell PythonAnywhere where our web app lives and what the Django settings file's name is.
Hit Save and then go back to the Web tab.
We're all done! Hit the big green Reload button and you'll be able to go view your application. You'll find a link to it at the top of the page.
If you see an error when you try to visit your site, the first place to look for some debugging info is in your error log. You'll find a link to this on the PythonAnywhere Web tab. See if there are any error messages in there; the most recent ones are at the bottom. Common problems include:
- Forgetting one of the steps we did in the console: creating the virtualenv, activating it, installing Django into it, migrating the database.
- Making a mistake in the virtualenv path on the Web tab – there will usually be a little red error message on there, if there is a problem.
- Making a mistake in the WSGI configuration file – did you get the path to your my-first-blog folder right?
- Did you pick the same version of Python for your virtualenv as you did for your web app? Both should be 3.6.