Django – Logging to File and Sending Emails when Exceptions Occurs

Categories Django, Python

Logging in any application is an important aspect of application design. Making sure that all errors/exceptions get logged in production help in finding issues. In this article, I am going to show how to do logging in a Django application.

Django usages python’s logging module for logging.  Logging configuration in python consists of 4 parts- Loggers, Handlers, Filters, Formatters. You can read more about these in Django documentation, but here is quick overview:

Formatters – As the name suggests, this describes the format of log text.

Filters – Filters can be used to filter out log records or to modify log records before they are logged.

Handlers – Handlers determine what happens to the log message. Log message can be written to file, printed on the screen,  emailed etc.

Loggers – Loggers are the entry point for logging. Here you define the handlers for the log, level of logging etc.

To configure logging in Django, a configuration dictionary needs to be provided to Django’s LOGGING settings.

Here is a sample configuration which logs to file and also sends emails to admins:

ADMINS = (('Harshveer', 'harshveer1889@gmail.com'), ('Harshveer', 'admin@harshveers.com'))
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'verbose': {
            'format': '%(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s'
        },
        'simple': {
            'format': '%(levelname)s %(message)s'
        },
    },
    'filters': {

    },
    'handlers': {
		'file': {
            'level': 'WARNING',
            'class': 'logging.FileHandler',
            'filename': os.path.join(BASE_DIR, "pyserver.log"),
			'formatter': 'verbose'
        },
        'mail_admins': {
            'level': 'WARNING',
            'class': 'django.utils.log.AdminEmailHandler',
            'formatter': 'verbose'
        }
    },
    'loggers': {
        'django': {
            'handlers': ['file', 'mail_admins'],
            'propagate': True,
            'level': 'WARNING',
        },
        'LoggerApp': {
            'handlers': ['file', 'mail_admins'],
            'propagate': True,
            'level': 'WARNING',
        }
    }
}

Now whenever an exception occurs in LoggerApp or django app, it will be logged to pyserver.log and also an email will be sent to users defined in ADMINS setting.

To log message manually logging module can be used as below:

from django.http import HttpResponse
import logging

# Get an instance of a logger
logger = logging.getLogger(__name__)

def log_error(request):
	logger.error('This is the manual error logging.')
	return HttpResponse("Logged manual error.")

That’s all about configuring logging in Django app. You can find complete project code for this on GitHub.

If you liked the post or have any suggestions, leave a comment 🙂

Sending Template Based Emails from Django

Categories Django, Python

Sending Emails from Django is quick and easy. In this post I will show a basic setup for sending Emails from Django using Email templates. Using templates give us the advantage of using one Email template to send Emails to different users with different data.

First we ned to setup a SMTP server locally for development environment. There are many ways to setup SMTP server for development environments.

One of them is to use Python’s build-in way to start a “dumb” SMTP server. Run this command in terminal to start python SMTP server on local environment:

python -m smtpd -n -c DebuggingServer localhost:25

This will show Emails in terminal itself. There are other SMTP servers available with UI also. The one I user is MailSlurper. This runs locally and has browser based UI.

We need to define SMTP host and port in Django projects’s settings.py:

SERVER_EMAIL = 'root@localhost'
EMAIL_HOST = 'localhost'
EMAIL_PORT = '25'
EMAIL_HOST_USER = ''
EMAIL_HOST_PASSWORD = ''

Create a directory for Email templates in you project, let’s say template. Add this directory to TEMPLATES setting of Django project’s settings.py.

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, "templates")],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

Create a template for subject email_subject.html with content as template for subject. Don’t use new lines in subject template. Add {{ subject }} to contents of email_subject.html file.

Create template for body of email named email_body.html. Add following content to this template:

Hi {{ name }},

This is a demo for sending emails from django using email templates.<br/>

Thanks,
{{ sender }}

In Django view import settings, loader and send_mail:

from django.template import loader
from django.core.mail import send_mail
from MailProject import settings

To send Email in Django view’s function, we will first get and parse Email templates and then send the Email:

def send_email(request):
	# Data for parsing email templates
	context_data = {
		'subject': 'Sent from django',
		'name': 'Harshveer Singh',
		'sender': 'Django Server'
	}

	# Get Subject template
	subject_t = loader.get_template('email_subject.html')
	# Parse Subject template
	subject = subject_t.render(context_data)
	# Get Body template
	body_t = loader.get_template('email_body.html')
	# Parse Body template
	body = body_t.render(context_data)
	
	try:
		# Send mail
		send_mail(subject, body, settings.SERVER_EMAIL, ['harshveer1889@gmail.com'], fail_silently=False,)
	except:
		return HttpResponse("Failed to send email.")

	return HttpResponse("Email sent successfully.")

Now, if we call this method, it will send the Email and we can see this message in MailSlurper.

That’s all about sending Emails in Django using Templates. You can find complete project code for this on GitHub.

If you liked the post or have any suggestions, leave a comment 🙂