Sentry Answers>Django>

Log and visualize user action history in Django

Log and visualize user action history in Django

David Y.

The ProblemJump To Solution

I am building a web application using Django and want to monitor user actions such as logins, password changes, and profile updates – basically any action a user can take in my app. I would then like to query this information and get statistics and visualizations from it, for example, a graph showing monthly logins, or weekly profile updates. How should I go about doing this?

The Solution

We can log user actions in Django by building and using a new UserAction model. First, we’ll create the model as below:

Click to Copy
from django.db import models from django.contrib.auth.models import User class UserAction(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE) action = models.CharField(max_length=255) timestamp = models.DateTimeField(auto_now_add=True) def __str__(self): return f'{self.user.username} {self.action} at {self.timestamp}'

We’ve included a reference to the user, a string for the action, and a timestamp. Depending on your application’s needs, you may require additional fields.

Next, we need a function to create log entries for user actions, like the one below:

Click to Copy
def log_user_action(user, action): UserAction.objects.create(user=user, action=action)

Finally, we can call this function in our views or signals, whenever an action has been taken.

Click to Copy
# After a user logs in: log_user_action(request.user, 'login') # After a user changes their password: log_user_action(request.user, 'password change')

All user actions we record with this logging function will now be stored as records in our database, and we can query them in the same way we would query any Django model. For example, we could write this function to return the count of a given action taken by one or all users over a specified period (defaulting to one month):

Click to Copy
from django.utils import timezone from dateutil.relativedelta import relativedelta def user_action_count(action, days=30, user=None): start_date = timezone.now() - relativedelta(days=days) if user: # actions by one user return UserAction.objects.filter(user=user, action=action, timestamp__gte=start_date).count() else: # actions by all users return UserAction.objects.filter(action=action, timestamp__gte=start_date).count()

We could then call this function as follows:

Click to Copy
# Get all user logins for the month logins = user_action_count('login') # Get all user password changes for the quarter password_changes = user_action_count('password change', 90) # Get all profile changes of the logged in user for the week profile_changes = user_action_count('profile change', 7, request.user)

We can then use this data in our views either directly or in graphs built with common data visualization libraries such as Chart.js or D3.js.

As an alternative to writing this functionality ourselves, we could achieve this functionality using an open-source library such as django-easy-audit or django-simple-history. The django-easy-audit library is the simplest to set up and will automatically start logging every create, read, delete, and update on every model in your project, as well as authentication events and URL requests. The django-simple-history library requires a bit more setup but allows you to be more selective about which models and actions you track.

Django also includes built-in action logging as part of its admin site to log actions taken by admins using LogEntry objects. While this can be used outside the admin panel, it’s considered a private API and changes to its functionality for Django 5 have not been officially documented as of this writing. For this reason, and to avoid mixing user action logs with admin action logs, we don’t recommend implementing this functionality using LogEntry objects.

  • Community SeriesIdentify, Trace, and Fix Endpoint Regression Issues
  • ResourcesBackend Error Monitoring 101
  • Syntax.fm logo
    Listen to the Syntax Podcast

    Tasty treats for web developers brought to you by Sentry. Get tips and tricks from Wes Bos and Scott Tolinski.

    SEE EPISODES

Considered “not bad” by 4 million developers and more than 100,000 organizations worldwide, Sentry provides code-level observability to many of the world’s best-known companies like Disney, Peloton, Cloudflare, Eventbrite, Slack, Supercell, and Rockstar Games. Each month we process billions of exceptions from the most popular products on the internet.

© 2024 • Sentry is a registered Trademark
of Functional Software, Inc.