Deploying cookiecutter-flask for free using pythonanywhere
Tags: flask, python, cookiecutter, pythonanywhere
Published: 2023-12-18 04:56:50

Welcome! You are about to start on a journey about and how to deploy your cookiecutter-flask project for free in pythonanywhere.

## Table of Content
* [Prerequisites](#prerequisites)
* [Project](#project)
* [How](#how)
 * [Setup pythonanywhere](#setup-python-anywhere)
 * [Zip project](#zip-project)
 * [Upload project](#upload-zip)
 * [Unpack zip](#unpack-zip)
 * [Install dependencies](#install-dependencies)
 * [Edit WSGI](#edit-wsgi)
 * [Virtualenv](#virtualenv)
 * [Environment Variables](#environment-variable)
 * [Install Node.js](#install-node-js)
 * [Install Npm packages](#install-npm-packages)
 * [Running flask command](#running-flask-command)
* [Support] (#support)

In this articles, i won't talk to much about why choose flask framework over other framework. IMHO flask good enough for most project because of lightweight and easy to scale based on our requirements.

## Prerequisites
Before jumping to how, you need to make sure you have: 

* Flask project ready to be deployed, you can create one here [cookiecutter-flask](https://github.com/cookiecutter-flask/cookiecutter-flask)
* [Pythonanywhere account](https://www.pythonanywhere.com/login/?next=/pricing/)


## Project
For demonstration purpose i'll be using my own project that generated directly from `cookiecutter-flask` without any modification, you can check it [here](https://github.com/vousmeevoyez/cookiecutter-flask-pythonanywhere).


## How
PythonAnywhere makes it easy to create and run Python programs in the cloud. To make it easier to understand we just treat pythonanywhere as another computer or server that we have limited access. 

Here are the high level step by step on how to run our flask project in pythonanywhere:

1. Setup pythonanywhere web application
2. Zip the project
3. Upload zip.
4. Unzip project.
5. Install dependencies
6. Edit wsgi file
7. Virtualenv
8. Environment variable
9. Broken styling + Setup node.js
10. Execute necessary flask command.

### Setup pythonanywhere <a name="setup-python-anywhere"></a>
You need go to pythonanwhere dashboard and create web app


![create web app in pythonanywhere](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jqzlbvs60l6neb6flm3z.png)


You should seen something like this.

![you have no web application](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dldgljl6q722fdyh43lu.png)


Now you can click add new web app

![Add new web app](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/38pp33ux2bbnsdg7ugic.png)

Select python web framework

![Select python web framework](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cfk3aefj0ybhgjfmsbz8.png)


Select python version, any version would be fine i think but for this article i'll just choose python 3.10




![Select python version](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ud45876ciji11qdssd7k.png)


No specific configuration required here, pythonanwhere will automatically bootstrap the flask project in the default directory.


![Flask setup](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zeing0n537jzuf08xars.png)

After that you will be redirected to web application page 

![web application](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lu159ux68ax8s74c4wzn.png)

Now if you click the generated url you should be able to see 'hello from flask!'

![hello from flask](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c1fehmlvp4e26qmkj11e.png)

Now we are ready to prepare to upload our code.

### Zip project <a name="zip-project"></a>
To make the whole project portable and easier to access in pythonanywhere server it's better to zip the project.

You could do it from cli but i prefer to push all my code into github repository and download the zip from there.

![download zip from github](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j1ezxn7w5683athq67t7.png)

### Upload the zip <a name="upload-zip"></a>

After we have zip file to upload we can go straight to pythonanywhere dashboard. Go to files, you will see something like this.

![files](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sagyq24sbrxb1pvz3ybj.png)

you can click `mysite` and upload your zip file from there.


![upload zip here](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jf0x9ml3kf5p8tv8po89.png)

After succesfully uploading your zip you will see your file in the list.

![succesfully upload the zip](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ve1bjqvzql68akarle9s.png)

### Unpack the zip <a name="unpack-zip"></a>

Still in the same screen, you can click open the bash console here button. 

After few second you should be able to see the console screen.


![bash console](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lr12t8hqkihc5le7g2mk.png)

now we can unzip the file using the following shell command
```
mv cookiecutter-flask-pythonanywhere-main.zip .. 
mv flask_app.py ..
cd ..
rm -rf mysite
unzip cookiecutter-flask-pythonanywhere-main.zip
mv cookiecutter-flask-pythonanywhere-main mysite
mv flask_app.py mysite
```
the command above basically unzip the project into mysite directory

![Unzipped project](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7yudvllyiusdt47iuoxx.png)

> Quick tips: ensure your website still up and showing hello from flask!

### Installing dependencies <a name="install-dependencies"></a>

Open bash console again and go to my site


![bash console](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3m0zcctt22cpmt0q9pj1.png)

```
virtualenv venv
source venv/bin/activate
pip install -r requirements.txt 
```

Now the installation process should be downloading.

![Installing requirements.txt](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kds3zw20sk5lhbuofkl4.png)


### Edit WSGI <a name="edit-wsgi"></a>
Since now we have the code uploaded and python dependencies installed we can update or wsgi script to connect with our flask entrypoint file instead of the one created by pythonanywhere.

You can go to your web app and click WSGI configuration file


![WSGI Configuration file](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uy4jt7bf2dbsedvr9j25.png)

Now you can comment the last line so it look like this.

```
#from flask_app import app as application  # noqa
from autoapp import app as application
```
You can save and reload file.


![Edit WSGI configuration file](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/56xbei9dpa35e19j982n.png)

you can try access the project url, but you will receive error 

> Something went wrong :-(


![first 500 error](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jrmaqqzzajsdfy7y2cfj.png)

Where going to debug it in the next step.


### Virtualenv <a name="virtualenv"></a>

Go back to web application dashboard 

![error log dashboard](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3bx4m65xlomc02597o09.png)

Click error log.

![ModuleNotFoundError](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1iaedvzrji7z3bhcb2fb.png)

> Looks like pythonanywhere unable to locate our installed dependencies that we install before through virtualenv

To fix this we just need to setup virtualenv on our web application.

- Go to web application and look for virtualenv
- Enter the path where we install our project dependencies through virtualenv
```
/home/kelvinswarna/mysite/venv
```

![virtualenv](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/py2ekd99i40lnyqwsd3v.png)

Now you can try access the project website again and you should see different error.

```
2023-12-18 03:55:01,806: Error running WSGI application
2023-12-18 03:55:01,814: environs.EnvError: Environment variable "DATABASE_URL" not set
2023-12-18 03:55:01,814:   File "/var/www/kelvinswarna_pythonanywhere_com_wsgi.py", line 16, in <module>
2023-12-18 03:55:01,814:     from autoapp import app as application
2023-12-18 03:55:01,814: 
2023-12-18 03:55:01,815:   File "/home/kelvinswarna/mysite/autoapp.py", line 5, in <module>
2023-12-18 03:55:01,815:     app = create_app()
2023-12-18 03:55:01,815: 
2023-12-18 03:55:01,815:   File "/home/kelvinswarna/mysite/cookiecutterflask/app.py", line 27, in create_app
2023-12-18 03:55:01,815:     app.config.from_object(config_object)
2023-12-18 03:55:01,815: 
2023-12-18 03:55:01,815:   File "/home/kelvinswarna/mysite/venv/lib/python3.10/site-packages/flask/config.py", line 231, in from_object
2023-12-18 03:55:01,815:     obj = import_string(obj)
2023-12-18 03:55:01,816: 
2023-12-18 03:55:01,816:   File "/home/kelvinswarna/mysite/venv/lib/python3.10/site-packages/werkzeug/utils.py", line 595, in import_string
2023-12-18 03:55:01,816:     __import__(import_name)
2023-12-18 03:55:01,816: 
2023-12-18 03:55:01,816:   File "/home/kelvinswarna/mysite/cookiecutterflask/settings.py", line 16, in <module>
2023-12-18 03:55:01,816:     SQLALCHEMY_DATABASE_URI = env.str("DATABASE_URL")
2023-12-18 03:55:01,816: 
2023-12-18 03:55:01,816:   File "/home/kelvinswarna/mysite/venv/lib/python3.10/site-packages/environs/__init__.py", line 116, in method
2023-12-18 03:55:01,816:     raise EnvError('Environment variable "{}" not set'.format(proxied_key or parsed_key))
2023-12-18 03:55:01,816: ***************************************************
2023-12-18 03:55:01,817: If you're seeing an import error and don't know why,
2023-12-18 03:55:01,817: we have a dedicated help page to help you debug: 
2023-12-18 03:55:01,817: https://help.pythonanywhere.com/pages/DebuggingImportError/
2023-12-18 03:55:01,817: ***************************************************
```
It's related to environment variable, where going to fix it in the next step.

### Environment Variable  <a name="environment-variable"></a>

There are some things we just shouldn’t share with our code. These are often configuration values that depend on the environment such as debugging flags or access tokens for APIs. Environment variables are a good solution and they are easy to consume in most programming languages.

To fix this we need open the bash console again and go to `mysite` we have environment variable template that we can use 


```
cp .env.example .env
```


![environment variable copied](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m8mcg47kuowpvsp4ecno.png)


Now we can try access the project website again and you should able to see the actual website now.


![Broken styling](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/10yoa759wc126v1hzc8f.png)

However the ui is not looking good since the styling is broken.

### Install Node.js <a name="install-node-js"></a>

The cookiecutter-project is running using [Flask-Static-Digest](https://github.com/nickjj/flask-static-digest) so we need node.js and webpack to generate our static asset.

Luckily pythonanywhere provide some [quickstart](https://help.pythonanywhere.com/pages/Node/) guide if we want to install node to our server 

We need open a new bash console and go to our root directory.
Will be something look like this


```
04:26 ~ $ ls
README.txt  cookiecutter-flask-pythonanywhere-main.zip  mysite
04:26 ~ $ 
```

now we can paste the command to download and install NVM
```
git clone --depth 1 https://github.com/creationix/nvm.git
source ~/nvm/nvm.sh
```

Now our server should have access to `nvm` and we can install node 18

![nvm installed](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t6ssineoklv2oricffue.png)

```
nvm install 18
```

![install node18 using nvm](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1wv2dpmwmjflpmzifsav.png)

Now we can move on to the next step which actually install our npm packages.

### Install Npm packages <a name="install-npm-packages"></a>


Open a new bash console and go to `mysite`

```
npm install
npm run-script build

```

### Running flask command <a name="running-flask-command"></a>


Open a new bash console and go to `mysite`

```
flask db init
flask db migrate
flask db upgrade
```


## Troubleshoot

Coming Soon!