arrow_back Volver
Inicio keyboard_arrow_right Artículos keyboard_arrow_right Artículo

¿Cómo realizar el deploy de una aplicación Django a Heroku?

Eduardo Ismael Garcia

Full Stack Developer at Código Facilito.

av_timer 7 Min. de lectura

remove_red_eye 45398 visitas

calendar_today 22 Diciembre 2018

En esta ocasión aprenderemos a desplegar nuestro proyecto Django en los servidores de Heroku. Hemos elegido Heroku puesto que este es un servicio el cual nos permite el despligue de nuestras aplicaciones de una forma muy sencilla, soporta múltiples lenguajes de programación, incluido Python y nos ofrece un plan completamente gratuito, con lo cual no existe excusa alguna para no tener un proyecto en línea 😎.

Antes de comenzar debes tener en cuenta que el post fue escrito para un proyecto Django en su versión 2.1, de igual forma, el proyecto se encuentra utilizando un control de versiones, en este caso git. Los únicos requerimientos para seguir el post es contar con un proyecto Django y con una cuenta en Heroku.

Librerías.

Lo primero que debemos de hacer es instalar, quizás, la librería más importante de todas, me refiero a gunicorn. gunicorn es un servidor HTTP para Unix, sin él, será prácticamente imposible realizar el despliegue 😬.

pip install gunicorn

Para este tutorial trabajaremos con el gestor de base de datos PostgreSQL, es por ello que la siguiente librería a instalar será psycopg2.

pip install psycopg2==2.7.4

Para realizar la conexión entre el proyecto y el gestor de base de datos usaremos la librería dj-database-url, esto principalmente, ya que Heroku nos proveerá de una base de datos que no se encuentra en el mismo servidor (lo cual no es nada malo); Es por ello que será necesario realizar la conexión mediante una url.

pip install dj-database-url

Para que podamos iniciar el servidor haremos uso de ciertas variables de entorno. Recordemos que las variables de entorno son una excelente forma en la cual podemos almacenar datos sensibles, por ejemplo, llaves secretas, tokens, passwords etc.... Para la lectura de dichas variables podemos apoyarnos de la ya clásica librería os, sin embargo, yo de forma personal recomiendo usar la librería decouple, una librería muy fácil de utilizar y que sin duda nos ahorrará un par de líneas de código.

pip install python-decouple

Listo, estas serían todas las librerías necesarias para poder realizar el deploy. Una vez instaladas cada una de ellas, el siguiente paso es generar nuestro archivo requirements.txt, archivo donde colocaremos todas las dependencias del proyecto.

Para generar dicho archivo ejecutaremos la siguiente sentencia.

pip freeze > requirements.txt

A partir de requirements.txt, el servidor instalará todas las dependencias necesarias para que el proyecto funcione correctamente; La instalación se hará de forma automatica al momento de realizar el deploy, es por ello que es de suma importancia que siempre que agreguemos una nueva librería al proyecto modifiquemos dicho archivo.

Tip: Una forma en la cual puedes instalar todas las dependencias de un proyecto sin tener que instalar librería por librería, será ejecutando la siguiente sentencia (El archivo requirements.txt ya deberá existir).

pip install -r requirements.txt

Esto es muy útil cuando nos incorporamos a un nuevo equipo de desarrollo 😉.

Configuraciones

Bien, ya tenemos las librerías instaladas, ahora, lo que debemos de hacer es modificar nuestro proyecto. Nos concentramos en el archivo settings.py.

Lo primero que haremos será modificar nuestra constante DEBUG, colocamos su valor como False.

DEBUG = False

Posteriormente asignamos los hosts válidos. En este caso coloco asterisco , indicando que acepte todos los hosts.

ALLOWED_HOSTS = ['*']

Configuramos nuestra base de datos. En este caso me apoyo de la librería decouple con su función config, de tal forma que podamos leer la variable de entorno DATABASE_URL, variable que crearemos en un par de minutos.


import dj_database_url
from decouple import config

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

Ahora trabajamos con los archivos estáticos. Esto puede ser un dolor de cabeza para los nuevo desarrolladores, y con mucha razón, en versiones anteriores de Django las configuraciones serán muchas y los pasos a seguir en ocasiones difíciles, afortunadamente esto ha ido mejorando en cada nueva versión 😅.

Agregamos las siguientes líneas de código al final de nuestro archivo settings.py.

STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
STATIC_URL = '/static/'

STATICFILES_DIRS = (
    os.path.join(BASE_DIR, 'static'),
)

Cómo sabemos (o si no, ahora ya lo sabes) Django no soporta servir archivos estáticos en producción, así que nos apoyaremos de WhiteNoise, una librería fantástica que sin duda nos ayudará en este problema.

Instalamos WhiteNoise (Lo siento, una librería más 🙈. Es la última, lo prometo).

pip install whitenoise

Recordemos la regla, si agregamos una nueva librería debemos modificar el archivo requirements.txt.

pip freeze > requirements.txt

Una vez instalado WhiteNoise, procedemos a agregar el middleware WhiteNoiseMiddleware.

MIDDLEWARE = [
         ...
     'whitenoise.middleware.WhiteNoiseMiddleware',
]

Finalizamos agregando la siguiente línea de código al final del archivo settings.py.

STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'

Uff, muchas configuraciones, y aun faltan un par más 😰. Ya casi acabamos.

En el archivo urls.py (el principal) agregamos las siguientes líneas de código, esto con la finalidad de poder utilizar los archivos estáticos.

from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [
    ...
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)

Generamos una nueva carpeta llamada static. Esta carpeta es cien por ciento obligatoria. Al nosotros realizar el deploy Heroku ejecutara, de forma automatica, la instrucción python manage.py collectstatic --noinput, si esta carpeta no existe obtendremos un error.

La carpeta static debe de encontrarse en la raiz del proyecto, al mismo nivel que el archivo manage.py.

Como Git (el control de versiones que estoy utilizando) no permite trabajar con carpetas vacías, será necesario agregar un nuevo archivo a cada una de las carpetas. Yo recomiendo un archivo .keep. Claro, tu puedes colocar el archivo que desees.

Y el último paso, el más importante, junto con la instalación de gunicorn, será crear el archivo Procfile. Este archivo debe encontrarse en la raiz del proyecto. Dentro del archivo colocamos la siguiente sentencia.

web: gunicorn <el nombre de tu proyecto>.wsgi --log-file -

Listo, ya hemos configurado de manera exitosa nuestro proyecto. Fueron muchos pasos, sin embargo, todos son necesarios y deben seguirse en ese mismo orden para evitar errores.

Aplicación Heroku.

Lo primero que haremos será autenticarnos con Heroku.

heroku login

Una vez autenticados, el siguiente paso será crear nuestra aplicación.

heroku create <nombre de tu aplicación heroku>

Si la aplicación se creó de forma satisfacoria, podemos ingresar a nuestro dashboard y encontrar nuestra aplicación.

Ligamos el repositorio a nuestra app en heroku.

heroku git:remote -a <nombre de tu aplicación heroku>

Si todo ha salido bien, procedemos a crear nuestra base de datos.

heroku addons:create heroku-postgresql:hobby-dev

Al nosotros crear la base de datos se creara, de forma automatica, la variable de entorno DATABASE_URL, variable que almacena la url de la base de datos.

Con la base de datos creada realizamos el Deploy. Este paso puede tomar un par de minutos dependiendo del tamaño de tu proyecto y tu conexión a internet, así que no desesperes 😬.

git push heroku master

¿Todo bien?, Perfecto, ahora procedemos a ejecutar todas las migraciones.

heroku run python manage.py migrate

Si así lo deseamos podemos hacer un par de pruebas con nuestros modelos.

heroku run python manage.py shell

Sin duda fueron muchas pasos, pero todo tiene su recompensa. Ejecutamos :

heroku open

Y de esta forma podremos visualizar nuestro proyecto en línea. 😎 (Claro, tambíen podemos ir a nuestro dashboard > settings> Domains and certificates, y allí encontraremos la url para acceder a nuestro sitio web 😃).

Si queremos echa un vistazo a los logs ejecutamos la siguiente sentencia.

heroku logs

Variables de entorno

Nuestro proyecto esta en línea, sin embargo, aun hay un par de cosas que nos hacen falta pulir para poder terminar el deploy de forma exitosa.

En este caso, si ejecutamos nuestro proyecto de forma local tendremos un error 😓 (Quizás más). El error hace referencia a nuestra base de datos y a la variables de entorno DATABASE_URL, variable que únicamente existe en el servidor y no de forma local.

Lo que yo recomiendo es generar un nuevo archivo llamado settings_production.py. Y será en este archivo donde colocaremos todas las configuraciones para que el proyecto pueda ejecutarse en producción (en el servidor).

En mi caso el archivo quedaría de la siguiente manera (El archivo lo coloque al mismo nivel que settings.py).

import dj_database_url
from decouple import config

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

Y en el archivo settings.py colocó, nuevamente, las configuraciones para mi base de datos de forma local.

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}

Para que mi proyecto sepa en qué entorno se encuentra ejecutándose, ya sea el desarrollo o producción, me apoyaré de un par mas de variables de entorno. Estas variables las vamos a crear en el servidor.

En mi caso generó tres variables más. Django_DEBUG cuyo valor será False, DJANGO_PRODUCTION, cuyo valor será True y _SECRET_KEY cuyo valor será un un string alpha númerico ( Tu coloca el valor que creas conveniente).

Una vez con las variables, nuevamente, modificamos el archivo settings.py. Sustituimos dos líneas de código.

DEBUG = config('DJANGO_DEBUG', default=True, cast=bool)

SECRET_KEY = config('SECRET_KEY', default='Coloca la llave default que proporciona Django')

Y en la última línea del archivo agregamos el siguiente código.

if config('DJANGO_PRODUCTION_ENV', default=False, cast=bool):
    from .settings_production import *

Y listo, de esta forma nuestro proyecto sabrá en qué entorno se ejecuta. En mi caso o producción o desarrollo, sin embargo, tú puedes tener la n cantidad de entornos que necesites.

Para confirmar que todo esto funciones hacemos un commit a nuestra rama principal, actualizamos el servidor y probamos de forma local y remota.

Si la página web funciona en ambos entornos, felicidades, has desplegado una aplicación Django en Heroku 🥑.

__

Bien, esto sería todo por esta ocasión. Espero el tutoríal haya sido de ayuda y si así lo fue, no dudes en compartir tus sitios webs con nosotros 🐊🍻.