Desarrollo y deploy de un proyecto en Django con PostgreSQL en Heroku
Tags: beginners, flask, python, heroku
Published: 2021-12-13 10:30:07

Realizar este simple tareas a veces se vuelven algo complejas y confusas, ya que la tecnología es un medio constantemente, en cambio, por lo cual hay que lidiar con varias versiones de estas herramientas. Pero aquí presento un pequeño guía de como lidiar con ello.

###<center>...</center>
&nbsp;

## Preparar entorno de trabajo
Para empezar debemos prepara nuestro entorno de trabajo. Para lo cual vamos a tipear los siguientes comando en la terminal.

> Nota: Estoy usando una terminal de Ubuntu con WSL.

Instalamos python y su gestor de paquetes.

`sudo apt-get install python3 python3-pip`

Luego instalamos la línea de comandos de [Heroku](https://devcenter.heroku.com/articles/heroku-cli#ubuntu-debian-apt-get).

`curl https://cli-assets.heroku.com/install.sh | sh`

Por último y no menos importante, vamos a instalar la línea de comando de Django para tareas Administrativas.

`python3 pip3 install django-admin`

> Si en la instalación de este último, no se encuentra el comando django-admin, se es necesario agregar la ruta del script al $PATH de la terminal.

```
export PATH="/home/[user]/.local/bin:$PATH"
# Cambiar la variable '[user]' por el nombre correspondiente de su nombre de usuario de la pc.
```

Ok, ya hemos instalado todas dependencias necesarias en nuestro entorno de trabajo.

###<center>...</center>
&nbsp;

## Instalar y configurar PostgreSQL.

Instalamos PostgreSQL y dependencias para trabajar con django.

`sudo apt-get install postgresql python-dev libpq-dev`

Configuramos la contraseña del usuario postgres y cambiar a dicho usuario.

```
passwd postgres
# Ingresa la contraseña cuando te lo pida.
su postgres 
```

### Crear Base de datos y Usuario

Creamos la base de datos y su usuario correspondiente, ademas de establecer su contraseña.

```
createdb [django]
createuser [django]
psql
ALTER USER [django] WITH PASSWORD '[anytoken]';
# Cambiar las variable '[django]' y '[anytoken]' por cualquier valor correspondiente.
```

###<center>...</center>
&nbsp;

## Crear nuestro proyecto con Django

Ahora vamos a crear nuestro proyecto con django-admin, con el siguiente comando.

```
django-admin startproject [django_postgres]
cd [django_postgres]
# Cambiar la variable '[django_postgres]' por el nombre real de tu proyecto.
```

el cual nos va a generar los archivos base de un proyecto a desarrollar con [django](https://django-project-skeleton.readthedocs.io/en/latest/structure.html).

```
django_postgres
  |-- django_postgres
  |  |-- __init__.py  
  |  |-- asgi.py
  |  |-- settings.py
  |  |-- urls.py  
  |  |-- wsgi.py
  |-- manage.py
```

### Iniciar el entorno virtual

Para tener un entorno controlado y no tener problemas con dependencias externas, creamos un entorno virtual con python usando el siguiente comando.

```
python3 -m venv venv
source venv/bin/activate# En caso de querer desactivar el entorno virtual, se es necesario usar el siguiente comando.
(venv) deactivate
```

### Instalar dependencias del proyecto

Django, es la librería central de la app y su dependencia principal.

`(venv) pip3 install Django`

Psycopg2, no permite conectarnos a cualquier motor de base de datos, y por lo tanto debemos instalarlo para poder conectarnos con nuestra base de datos con PostgreSQL.

`(venv) pip3 install psycopg2`

[Gunicorn](https://gunicorn.org/), es un servidor WSGI, el cual trabaja junto con Heroku. Necesario para el deploy.

`(venv) pip3 install gunicorn`

[Django-heroku](https://github.com/heroku/django-heroku), es una librería de Heroku, que configura todas la variable globales de la app.

`(venv) pip3 install django-heroku`

### Configuración del proyecto

Conectar nuestro proyecto con la base de datos de forma local, debemos establecer las credenciales, que se gestiono anteriormente en el archivo `django_postgres/settings.py`

```
# django_postgress/settings.py
...
# Database
# https://docs.djangoproject.com/en/3.0/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': '[django]',
        'USER': '[django]',
        'PASSWORD': '[anytoken]',
        'HOST': 'localhost',
        'PORT': '5432'
    }
}
...
# Cambiar las variable '[django]' y '[anytoken]' por cualquier valor correspondiente.
```

### Correr el proyecto

Comprobamos el correcto funcionamiento del proyecto hasta ahora.

`(venv) python3 manage.py runserver`

Lo que nos dará como resultado al visitar la siguiente [link](http://localhost:8000/).

![Launch project](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nw6y64gw2tlp0wgjuyff.png)

Django nos ofrece una administración por defecto, la cual para acceder a ellas, tendremos que crear un usuario.

```
(venv) python3 manage.py createsuperuser

# Ingrese los datos que le pida el programa.
``` 

Ya realizado la operación anterior con éxito, nos dirigiremos al siguiente [link](http://127.0.0.1:8000/admin).
 

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

Ingresamos nuestras credenciales.


![Login admin](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bwvzu2yyovaxnlg3cj9q.png)

y vualá, ya tenemos nuestra administración funcionando.

###<center>...</center>
&nbsp;

## Deploy en Heroku

Llegamos a la mejor parte, donde nuestro trabajo sera accesible al publico. Para ello necesitamos modificar el proyecto para producción, y crear los archivos necesario para hacer el deploy en Heroku.

### Configuración proyecto para producción

Lo primero que debemos hacer es volcar todas las dependencias de librerías que usa nuestro proyecto en un archivo requirements.txt, con la ayuda del manejador de paquetes Python pip.

`(venv) pip3 freeze > requirements.txt`

Cual es el motivo para hacer esto, bueno muy sencillo, heroku necesita instalar las dependencias poder correr el proyecto en un dyno (así se denomina los contenedores en heroku).

> Nota: En algunas ocasiones, se puede presentar un error con la librería pkg-resource, por lo que en tal caso se debe eliminar del requirements.txt

```
# requirements.txt
...
 dj-database-url==0.5.0
 Django==3.0.4
 django-heroku==0.3.1
 gunicorn==20.0.4
 --pkg-resources==0.0.0
 psycopg2==2.8.4
 pytz==2019.3
 sqlparse==0.3.1
...
```

Luego, vamos a modificar nuestro archivo django_postgres/settings.py, y así prepara nuestro proyecto para producción, cambiando algunas variables globales.

El primer cambio va hacer agregar la librería django_heroku, para que se encargue de gestionar las variables globales.

```
# django_postgress/settings.py
...

import os
+++ import django_heroku

...# Al final del archivo.
...STATIC_URL = '/static/'+++ django_heroku.settings(locals())
...
```

El siguiente cambio va hacer, cambiar el comportamiento del proyecto a producción, para ellos necesitamos cambiar la variable global DEBUG = False.

```
# django_postgress/settings.py
...
# SECURITY WARNING: don't run with debug turned on in production!
+++ DEBUG = False
...
```

Otro archivo que tenemos que modificar es el archivo de rutas `django_postgres/urls.py`, al cual por conceptos de no extender tanto esta guía, vamos a usar como pages de inicio o index la misma que trae por defecto django en desarrollo. Ya que django en producción oculta dicha vista.

```
# django_postgress/urls.py
...from django.contrib import admin
from django.urls import path
+++ from django.views import debug

urlpatterns = [
    path('admin/', admin.site.urls),
    +++ path('',  debug.default_urlconf)
]
...
```

### Preparativos para el deploy en Heroku

En este antepenúltimo paso, vamos a crear los archivos necesario para hacer el deploy, para ello vamos crear dos archivos más Procfile y runtime.txt.

Procfile, contiene los comando necesario para ejecutar el proyecto y herramientas.

```
# Procfile
...web: gunicorn django_postgres.wsgi --log-file -
release: python3 manage.py migrate...
```

El primer comando web, ejecuta el proyecto. El segundo release ejecuta la migración hacia la base de datos de PostgreSQL en Heroku.

runtime.txt, le especifica a Heroku que versión de Python debe ejecutar el código Python para mantener su integridad.

```
# runtime.txt
...python-3.6.9
...
```

### Deploy en Heroku

Por ultimo, llegamos al deploy en Heroku. Para ello necesitamos tener creado una cuenta en Heroku.

Ya teniendo creada una cuenta en Heroku, procedemos a crear un app en Heroku, lo podremos hacer por medio del panel de control de la interfaz de Heroku, o por medio de su linea de comando.

Para lo cual vamos a iniciar sesión en la linea de comando de Heroku, de la siguientes manera.

`(venv) heroku login`

Luego vamos a crear nuestra app.

```
(venv) heroku create --app [django_postgres]
# Cambiar las variable '[django_postgres] por el nombre de tu proyecto.
```

Heroku usa Git para administra las implementaciones de aplicaciones, para lo cual necesitamos inicializar un repositorio local con Git.

`(venv) git init`

Ahora debemos agregar un archivo .gitignore para ignorar los archivos de cache que genera python de forma automática y las dependencias venv.

`(venv) echo 'venv/\n.py[cod]\n' > .gitignore `

Creamos nuestro primer commit.

```
(venv) git add .
(venv) git commit -m 'Primer commit'
```

Agregar el repositorio remoto a Git para hacer el push a Heroku.

```
(venv) heroku git:remote --app [django_postgres]
# Cambiar las variable '[django_postgres] por el nombre de tu proyecto.
```

Ahora realizamos el push a Heroku.

`(venv) git push heroku master`

Este sera el resultado, el deploy del proyecto.

![Terminal output](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/av691yotw9p3ibso95kt.png)

Para abrir el proyecto al navegador desde la terminal, solo debemos ejecutar el siguiente comando.

`(venv) heroku open`

![Launch project](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nw6y64gw2tlp0wgjuyff.png)
Y vualá, tenemos nuestro proyecto en producción.