Cómo desplegar nuestro proyecto hecho con Django + PostgreSQL en Heroku

Joel Eche
heroku
django
postgresql

Como desarrolladores, alguna vez hemos tenido la necesidad de desplegar nuestras aplicaciones, y Heroku es una buena opción, sobretodo porque nos ofrece la posibilidad de utilizar bases de datos de manera gratuita, más específicamente PostgreSQL.

Por lo que en esa ocasión aprenderemos a desplegar nuestras aplicaciones hechas en Django a Heroku. Como consideraciones iniciales, tenemos elaborado un proyecto Django REST en el cual hemos utilizado Django 2.2.12 y Python 3.7.3 y al que llamaremos my_app.

Además, hemos modificado la configuración de nuestro proyecto, es decir, para este ejemplo hemos eliminado el archivo settings.py que se crea por defecto, con el fin de tener por separado un archivo de configuración para un entorno de desarrollo y otro para producción, ya que subiremos a heroku la configuración de producción. Teniendo la estructura:

my_app/
|--------settings/
|--------|-------- __init__.py
|--------|-------- base.py
|--------|--------development.py
|--------|--------production.py

Se debe tener en cuenta también que en el archivo base, se ha copiado la configuración que se genera por defecto en settings.py, y debe ser importada tanto en development.py y production.py, de la siguiente manera

from my_app.settings.base import *

Y para que esta nueva configuración funcione, en nuestro archivo manage.py, se configura de la variable DJANGO_SETTINGS_MODULE de la siguiente manera:

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'my_app.settings.production')

En este caso, hemos configurado a nuestra aplicación para que corra por defecto la configuración de my_app/settings/production.py.

Dicho esto, empezamos!

Configurando gunicorn

Es importante que en nuestro proyecto Django tengamos instalada la librería guricorn, que es un servidor WSGI(Web Server Gateway Interface), el cual nos permitirá comunicarnos a través del protocolo HTTP. Podemos pensar en gunicorn, como si fuera nuestro runserver, pero más robusto. Lo hacemos con el siguiente comando

pip install gunicorn

Ahora, crearemos el archivo Procfile en la raíz de nuestro proyecto, en este archivo declararemos qué comando queremos que se ejecute al iniciar nuestra aplicación. Dentro el este archivo colocamos lo siguiente:

web: gunicorn core.wsgi --env DJANGO_SETTINGS_MODULE='settings.production' --log-file -

"web" nos indica que declararemos un proceso de tipo web y lo siguiente será el comando que necesitaremos para ejecutarlo, la documentación de Heroku nos indica que web es importante ya que declara que este tipo de proceso será adjuntado a la pila de enrutamiento HTTP de Heroku y recibirá tráfico web cuando se implemente.

Configurando django-heroku

Luego instalamos la librería django-heroku, la cual realizará las configuraciones necesarias para Heroku, de manera automática:

pip install django-heroku

Podremos apreciar en nuestra consola que aparece lo siguiente:

Collecting django-heroku
  Using cached django_heroku-0.3.1-py2.py3-none-any.whl (6.2 kB)
Collecting whitenoise
  Using cached whitenoise-5.1.0-py2.py3-none-any.whl (19 kB)
Collecting dj-database-url>=0.5.0
  Using cached dj_database_url-0.5.0-py2.py3-none-any.whl (5.5 kB)

Esto nos indica que al instalar django heroku, se instalarán también whitenoise, que le permite a nuestra aplicación servir archivos estáticos y dj-database-url, librería que nos brindará la conexión de la base de datos en un diccionario, que se generará a partir de la variable DATABASE_URL, que provee Heroku.

Importamos django-heroku a nuestro archivo de configuraciones de producción:

import django_heroku

Y lo activamos:

django_heroku.settings(locals())

Configurando PostgreSQL

Debido a que utilizaremos PostgreSQL, configuramos nuestra variable de configuración de producción, llamada DATABASES, de la siguiente manera:

DATABASES = {'default': dj_database_url.config(conn_max_age=500)}

En este caso no debemos preocuparnos por colocar la demás configuración, como el nombre de la base de datos, host y demás, ya que Heroku mediante django-heroku se encarga de cargar la configuración.

Con lo cual, tendríamos nuestro archivo de configuración para producción, de la siguiente manera:

from my_app.settings.base import *
import django_heroku
import dj_database_url

DEBUG = False
DATABASES = {'default': dj_database_url.config(conn_max_age=500)}

django_heroku.settings(locals())

Creación del archivo de requerimientos

Para generar el archivo de requerimientos requirements.txt, puedes hacerlo utilizando el siguiente comando

pip freeze > requirements.txt

Donde pip freeze lista los requerimientos que tenemos instalados y el operador > seguido de la ruta del archivo, indican que allí se copiará la salida que obtendremos de pip freeze.

Creación del archivo runtime

Además, creamos el archivo runtime.txt, en la raíz de nuestro proyecto, en este archico, colocamos

python-3.7.3

El cual le va a indicar a Heroku, la versión de Python que vamos a utilizar.

Hora del despliegue! :computer:

Ahora que tenemos lista la configuración para nuestro proyecto, vamos a proceder a hacer el deploy en Heroku, usando el terminal, es necesario tener Heroku CLI, si aún no lo tienes instalado, puedes seguir la siguiente guía https://devcenter.heroku.com/articles/heroku-cli de acuerdo a tu sistema operativo.

Iniciamos sesión en heroku, para ello ejecutamos desde el terminal:

heroku login

Ahora, procederemos a crear nuestro sitio, esta vez ejecutaremos:

heroku create my_app

En el caso de que no tengamos un nombre en mente, podemos ejecutar solamente:

heroku create

Pero ten en cuenta que heroku elegirá un nombre random par nuestro sitio, de todas maneras, siempre podemos cambiarlo haciendo uso de:

heroku apps:rename nuevo_nombre_del_site

Cuando ejecutamos heroku create, Heroku se encargó de crear un nuevo remote que apunta a heroku, a partir de aquí, solo necesitaremos hacer push hacia Heroku para así desplegar nuestra aplicación, ejecutamos :

git push heroku master

Esperamos un momento a que termine el deploy y debe aparecer el siguiente mensaje

remote:        https://my_app.herokuapp.com/ deployed to Heroku

Y tendremos ya nuestra aplicación desplegada :D

Pero ahora toca configurar Django xd

Configuración de Django en producción

Accedemos a la terminal de Heroku:

heroku run bash

Y estando dentro, corremos las migraciones:

python manage.py migrate

Procedemos luego a crear a nuestro superuser con:

python manage.py createsuperuser

Y ahora, ya tenemos nuestra aplicación lista para ser utilizada!.

Podemos confirmar que todo está trabajando correctamente, accediendo desde nuestro navegador a my_app.herokuapp.com/admin/ e iniciando sesión.

Notas

  • En el caso de que tengas algún error, puedes utilizar heroku logs --tail ,para obtener más información.

  • Si necesitas utilizar archivos estáticos, debes añadir a tu archivo de configuración :

STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__))
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(PROJECT_ROOT, 'static')

Y colocar el middleware de whitenoise justo después de la seguridad de Django.

MIDDLEWARE = [
   'django.middleware.security.SecurityMiddleware',
   'whitenoise.middleware.WhiteNoiseMiddleware',
...
]

Referencias

Configuring Django Apps for Heroku
Despliega tu sitio en Heroku (También como PythonAnywhere) Deploying Django to Heroku: Procfile, STATIC_ROOT, & Other Pitfalls Deploying Django to Heroku: Connecting Heroku Postgres