Logging en Django: cómo configurar y registrar errores paso a paso

Video thumbnail

Cuando trabajas con Django, una de las tareas más importantes es llevar un buen control de los errores. El logging en Django te permite registrar eventos, advertencias y fallos en un archivo para consultarlos después. Esto es clave en producción: sin logs, encontrar un error sería como buscar una aguja en un pajar.

En mi experiencia, he visto que muchos desarrolladores se quedan con el log por defecto que aparece en consola, y cuando algo falla en el cliente… no queda rastro. Justo ahí es donde el logging bien configurado te salva la vida.

¿Qué es el logging en Django y por qué es importante?

El logging es un sistema que registra lo que pasa dentro de tu aplicación. Django usa el módulo estándar de Python logging, lo que significa que puedes aprovechar toda la potencia de Python directamente en tu proyecto.

¿Por qué es tan importante?

  • Te permite detectar errores rápidamente.
  • Facilita la trazabilidad de procesos críticos (pagos, autenticaciones, envíos de emails).
  • Sirve como historial de auditoría en proyectos en producción.

Cómo funciona el sistema de logging en Django

El sistema de logging se basa en cuatro elementos principales:

  • Loggers → son los que generan los mensajes. Ejemplo: logger = logging.getLogger(__name__).
  • Handlers → deciden a dónde va el log (archivo, consola, email, etc.).
  • Formatters → definen el formato de salida: fecha, nivel, mensaje, etc.
  • Niveles de logging → marcan la importancia del evento:
    • DEBUG → mensajes de depuración.
    • INFO → información general.
    • WARNING → advertencias.
    • ERROR → errores que interrumpen procesos.
    • CRITICAL → fallos graves.

Implementando el logger

Para esto es muy sencillo:

import logging
logger = logging.getLogger(__name__)
  def example_token(self) -> str:
        ***        
        logger.error(f"Error en PayPal process order: {e}", exc_info=True)
        return ""

Es decir, importamos el módulo de logging:

import logging

Creamos una instancia (logger). (Le pasamos un nombre, que puede ser cualquiera (ej: PayPal)):

logger = logging.getLogger('paypal')

Usualmente se emplea una convención para que el logger tome automáticamente el nombre de la aplicación, pero realmente poco importa qué pongas:

logger = logging.getLogger(__name__)

Con esa instancia:

 ya podemos registrar cualquier error interno, simplemente pasando el mensaje de error correspondiente:

logger.error(f"Error en PayPal process order: {e}", exc_info=True)

Esto se puede hacer en cualquier parte del código.
Por ejemplo, en un try/except al momento de generar un token, o al procesar un pago.

Registrar errores en Django con logger en archivo

El problema es que, de manera predeterminada, el log aparece en la terminal, cosa que no queremos. Lo ideal es que se guarde en un archivo aparte que podamos consultar después.

Para eso hay que hacer una configuración adicional en Django:

settings.py

LOGGING = {
    'version': 1, # version definida por nosotros
    'disable_existing_loggers': False,  # importante para que Django siga mandando logs
    'formatters': {
        'verbose': {
            'format': '[{asctime}] {levelname} {name}: {message}', # formato de salida, ej 2025-09-07 12:25:10,456] ERROR store.views: Error en PayPal process order
            'style': '{',
        },
    },
    'handlers': {
        'file': {
            # 'level': 'DEBUG',  # captura todo desde DEBUG hasta ERROR
            'level': 'ERROR',  # captura todo desde DEBUG hasta ERROR
            'class': 'logging.FileHandler',
            'filename': os.path.join(BASE_DIR, 'logs', 'django.log'),  # archivo único
            'formatter': 'verbose',
        },
    },
    'root': {   # <-- logger global
        'handlers': ['file'],
        'level': 'DEBUG',
    },
}

Ojo con esto:

Django no crea la carpeta /logs automáticamente. Si no la creas tú, obtendrás una excepción como FileNotFoundError.

Esto hará, que se  registre un log que podemos revisar de manera periódica y se encuentra en:

djangoshopping\logs\django.log

Debes de crear la carpeta logs dentro del proyecto ya que Django no la crea automáticamente y daría un error como:

Exception in thread django-main-thread:
Traceback (most recent call last):
  File "***Lib\logging\config.py", line 604, in configure
    handler = self.configure_handler(handlers[name])
  File "***Lib\logging\config.py", line 869, in configure_handler
    result = factory(**kwargs)
  File "***Lib\logging\__init__.py", line 1218, in __init__
    StreamHandler.__init__(self, self._open())

Como consideraciones adicionales, con esto, definimos la data que vamos a registrar:

  • verbose, es un nombre que le queramos dar al formato.
  • asctime: fecha y hora.
  • levelname: nivel del log (DEBUG, INFO, ERROR, etc.).
  • name: el nombre del logger (ejemplo: store.views).
  • message: el texto que pasaste en logger.error("...").
  • style: '{'  indica que usamos llaves ({}) en lugar de % para formatear (más moderno).

El Handlers es a donde mandan los logs (archivo, consola, email, etc.):

  • level: 'ERROR',  Solo guarda logs de nivel ERROR o más graves (CRITICAL). (Si lo cambias a DEBUG, guardará todo (incluido debug e info)).
  • class: 'logging.FileHandler', Escribe en un archivo plano.
  • filename, el archivo donde se guarda (logs/django.log).
  • formatter: 'verbose', usa el formato que definimos antes.

Con la última parte:

    'root': {   # <-- logger global
       'handlers': ['file'],
       'level': 'DEBUG',
   },
}
  • Root logger, el logger global de Python.
  • handlers: ['file'], cualquier log que se genere en tu proyecto va a pasar por el handler file.
  • level: 'DEBUG', significa: acepto logs desde nivel DEBUG hacia arriba. OJO: Aunque el root acepte DEBUG, el handler tiene nivel ERROR. Eso significa que se procesan todos, pero solo se escriben los de error, esto se implemento asi de manera demostrativa, pero, lo correcto es que, para nuestro ejemplo, que coloques:
    'root': {   # <-- logger global
       'handlers': ['file'],
       'level': 'ERROR',
   },
}

Guardar logs en un archivo en Django

La diferencia clave entre consola y archivo es que el archivo es persistente.

  • En consola, los logs se pierden al reiniciar el servidor.
  • En archivo, quedan guardados para consultarlos en cualquier momento.

Con el FileHandler indicas exactamente dónde quieres guardarlos. Mi recomendación es que uses siempre una carpeta dedicada (/logs) dentro del proyecto para mantenerlo ordenado.

Mejores prácticas de logging en Django

Algunas lecciones aprendidas:

  • Usa niveles diferentes según el entorno: en desarrollo puedes usar DEBUG, en producción mejor ERROR o WARNING.
  • Define un formato claro con asctime, levelname, name y message.
  • No abuses del logging: demasiada información puede ser tan inútil como ninguna.
  • Asegúrate de que los logs sensibles (ej. datos de usuarios) no se guarden en texto plano.

Integración avanzada de logging

Más allá de un archivo .log, puedes enviar los logs a servicios externos:

  • Sentry → ideal para alertas de errores en tiempo real.
  • ELK Stack (Elasticsearch + Logstash + Kibana) → perfecto para proyectos grandes.
  • Datadog → observabilidad completa (logs, métricas y trazas).
  • Esto se logra configurando otros handlers como SMTPHandler, SysLogHandler o integraciones personalizadas.

Errores frecuentes y cómo resolverlos

  • “No such file or directory: logs/django.log” → Crea manualmente la carpeta /logs.
  • Root logger mal configurado → Si pones DEBUG en root pero ERROR en handler, se procesan todos pero solo se guardan errores. Ajusta ambos al mismo nivel.
  • Logs no se escriben en archivo → Verifica permisos de escritura en la carpeta de logs.

Preguntas frecuentes sobre logging en Django

  • ¿Dónde se guardan los logs en Django?
    Donde lo definas en filename dentro del handler, por ejemplo: BASE_DIR/logs/django.log.
  • ¿Cómo registrar errores personalizados?
    Creando un logger propio:
    • logger = logging.getLogger("mi_aplicacion")
      logger.warning("Advertencia personalizada")
  • ¿Cómo cambiar el nivel de logging en producción?
    Modifica el valor de level en root y en el handler:
    • 'level': 'ERROR'

Conclusión

Configurar correctamente el logging en Django es una de esas tareas que parecen secundarias, pero cuando ocurre un fallo crítico, agradeces haberlo hecho. En mi caso, más de una vez he podido detectar errores en procesos de pago gracias a tener un log detallado en archivo.

Mi recomendación: empieza con un FileHandler simple, añade un formato claro y, cuando tu proyecto crezca, da el salto a servicios externos como Sentry o ELK. Así tendrás control total de lo que ocurre en tu aplicación.

Acepto recibir anuncios de interes sobre este Blog.

Vemos los pasos para implementar un sistema de Logging , para registrar un log en Django.

| 👤 Andrés Cruz

🇺🇸 In english