Image

Django alerts with Tailwind and DaisyUI

Dani Hodovic Feb. 10, 2024 2 min read
Responsive image

When I quickly want to prototype a new idea I use a combination of:

  • Django
  • Tailwind with django-tailwind for UI auto-reloads on templates changes
  • DaisyUI for Tailwind components

Many sites use some sort of alerts to notify users of actions and site updates such as email subscriptions or successful payments. By combining the Django messages framework and DaisyUI alerts we get pretty alerts out of the box.

Django messages have various helpers which generate tags we can use in css classes:

  • messages.info(request, "Three credits remain in your account.") -- css-class:info
  • messages.success(request, "Profile details updated."): -- css-class:success
  • messages.warning(request, "Your account expires in three days."): -- css-class:warning
  • messages.error(request, "Document deleted."): -- css-class:error

Luckily all of the built-in tags map cleanly to DaisyUI alert classes:

Production Shell

Suppose we have a view that performs an action, publishes a message and redirects the user:

from django.contrib import messages
from django.views.generic.base import RedirectView
from django.contrib.auth.mixins import LoginRequiredMixin
from django.urls import reverse_lazy


class ActionView(LoginRequiredMixin, RedirectView):
    permanent = False
    url = reverse_lazy("core:index")

    def get_redirect_url(self, *args, **kwargs):
        messages.success(
            self.request,
            "You have triggered an action!",
        )
        return super().get_redirect_url(*args, **kwargs)

The call to messages.success will add a success tag to the message object in the template like so:

{% for message in messages %}
    <div role="alert" class="alert alert-{{ message.tags }}">
        <span>{{ message }}</span>
    </div>
{% endfor %}

The resulting HTML would be:

<div role="alert" class="alert alert-success">
    <span>You've triggered an action!</span>
</div>

The class alert alert-success automatically creates a DaisyUI alert component:

Production Shell

However, since Tailwind cleverly strips out unused css classes this won't work. Tailwind scans the HTML document on build time for what css classes are in use and only includes those in the resulting css build. Since our Django template dynamically generates the alert type alert alert-{{ message.tags }} we have to instruct Tailwind to keep certain classes in the final build even if they don't exist in the HTML document. We can do that by modifying the Tailwind config file tailwind.config.js. Simply add the generated class names in the safelist:

module.exports = {
  content: [
    '../templates/**/*.html',
  ],
  theme: {},
  plugins: [
    require('@tailwindcss/forms'),
    require('@tailwindcss/typography'),
    require('@tailwindcss/line-clamp'),
    require('@tailwindcss/aspect-ratio'),
    require('daisyui'),
  ],
  daisyui: {},
  safelist: [
    'alert-info',
    'alert-success',
    'alert-warning',
    'alert-error',
  ],
}