Add Some Magic to Your Django Website
Tags: python, django, javascript, unicorn
Published: 2020-08-17 03:10:21

---
title: Add Some Magic to Your Django Website
published: true
description: django-unicorn is a magical full-stack framework for Django ✨
tags: python, django, javascript, unicorn
cover_image: https://images.unsplash.com/photo-1585544313985-f84aac5abf7b?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=3634&q=80
series: django-unicorn
---

Django has been, rightly or wrongly, derided in some circles for not keeping up with modern web development. It even came up in some of the comments of the recent [Django Developers Survey](https://docs.google.com/forms/d/e/1FAIpQLSf-cXoD_VQNW7D8yWWP1dkcgw9JMM9cC8f4JMXqT8249rWpjg/viewanalytics). Personally, I don't find that judgment completely fair (all of the work done for asynchronous views is a prime example of Django innovating), however, the story of how to integrate Django with a modern frontend framework isn't super clear.

However, I believe that most sites don’t need a complicated frontend framework anyway. Most websites are not single-page applications (SPAs), but developers are incurring the bloat and site performance of a large frontend framework, in addition to creating more work. Following in the footsteps of the [Zen of Python's](https://www.python.org/dev/peps/pep-0020/) "Simple is better than complex", I prefer to eschew complexity unless it's needed.

Note: when I refer to "frontend frameworks", I am mostly thinking of [React](https://reactjs.org/), [Vue.js](https://vuejs.org/), [Ember](https://emberjs.com/), and [Angular](https://angularjs.org/). However, I am currently enamored with a few of the newer micro-frameworks (e.g. [Alpine](https://github.com/alpinejs/alpine), [htmx](https://htmx.org/)) and feel they present fewer of the issues I describe below.

# Dealing with Javascript build tooling, or: all that glitters isn't gold

Have you struggled with [gulp](https://gulpjs.com/), [grunt](https://gruntjs.com/), [browserify](http://browserify.org/) or [webpack](https://webpack.js.org/) in the past? (Pssst, I heard [Parcel](https://parceljs.org/) solves all your problems! Oh no, wait, maybe [esbuild](https://github.com/evanw/esbuild) will solve everything?) What happens when a new Javascript toolchain is now the "right" way to build your site? I'd rather not spend the time switching to another tool for incremental improvements because the state of the art changed once again. I would rather spend time working on my app then configuring how to build frontend assets.

Do you enjoy starting a Node.js process to watch for Javascript code changes every time you fire up the Django `runserver` management command? To me, it is just another complication that gets in the way of the developer experience.

# Building APIs and GraphQL, or: using a sledgehammer to crack a nut

The best practice to connect a Django app with a frontend framework is to build REST APIs or, more recently GraphQL. Building that API will take time and effort away from improving the core website functionality. Unless you expect to also support mobile applications, there is a lot of work involved to build a robust REST API. While [Django REST framework](https://www.django-rest-framework.org/) (DRF) is a brilliant library that encourages sane REST practices and reduces how much code is required for trivial implementations,  it is still another framework layered on top of Django. Even with trivial implementations, understanding how DRF works can be tricky.

GraphQL solves some of the object mapping and querying peculiarities of REST, but it has some of the same drawbacks as DRF. Creating serializers for every model and understanding the particular terminology is not trivial. Plus, there is the relatively new paradigm of how GraphQL works and the nuances of how it’s implemented.

Additionally, APIs frequently require authentication, authorization, CORs, and other security measures on top of any normal website functionality.

# Juggling frontends templates, or: throwing the baby out with the bathwater

To integrate a frontend framework into an existing Django site, you have to jump through some hoops so that Django leaves the Javascript framework du jour alone and doesn’t, for example, interpret Vue's `{{ }}` as Django template variables. While doable, it is just another thing to handle. The other complication is switching contexts between Django HTML templates and the frontend framework code. The Django HTML template tends to bootstrap the data and then let the frontend framework handle all of the heavy lifting.

The other approach is to skip Django’s HTML templates altogether and use the brand new API you just built. Either way, you are throwing away the Django template language, a robust and extensible way to convert data into HTML. While not as advanced or contained as frontend framework components, Django `includes` _can_ be used to build reusable UI components across a website.

# A full-stack framework for Django, or: thinking outside the box

Every time I start a new Django project, I go through the same mental calculations to decide how to handle the frontend of the site.

- Which CSS framework to use?
- How to configure a CSS pre-processor (e.g. SASS, Less, etc)?
- Use a Javascript framework or just piece together some micro-libraries and vanilla Javascript?
- Create a REST API? Set up GraphQL?

For some of these questions, I have some third-party applications I copy from project to project that mostly works, but it is complicated.

One thing I love about Python and Django is the "battery-included" approach. I know that Django has curated an integrated, stable, and secure platform to build server-side websites. I don’t want to have to make other decisions just to have a modern website experience — I just want to create -- not wade through a bunch configuration.

I have been jealously watching developers of other server-side frameworks solving the same issues, namely [Livewire](https://laravel-livewire.com/) in Laravel, a PHP web framework, and [Liveview](https://hex.pm/packages/phoenix_live_view) in `Phoenix`, an Elixir web framework. So, like every other unreasonable developer who doesn’t want to switch away from their preferred language, I thought "how hard could it be to build this in Django?!" (Turns out... it's hard!) I ported a small portion of the ideas from `Livewire` to Django to prototype how it might work over a weekend and [django-unicorn](https://www.django-unicorn.com/) was born.

I've had the definite benefit of someone smarter than myself forging ahead of me — being able to look at Livewire’s technical documentation and screencasts have been incredibly helpful to see exactly what pain points `Livewire` solves. I have also been inspired by major parts of how the Javascript portion of `Livewire` works.

Currently, [django-unicorn](https://www.django-unicorn.com/) is focused on simplicity and enabling 80% of what a modern website requires. There will always be a need for more complicated SPA frameworks, but if all you need is simple website interactions, then [django-unicorn](https://www.django-unicorn.com/) can provide that with a minimal of fuss already.

The basic building blocks are already available in version 0.3.0 of [django-unicorn](https://www.django-unicorn.com/), but I'm still smoothing out the rough edges and adding more functionality. [Documentation](https://www.django-unicorn.com/documentation) is also a work in process, but I'm slowly been adding to it to make it as useful as possible. I would love to hear feedback about the idea and additional features to improve the Django developer experience for others. The code is licensed as MIT and PRs are greatly appreciated at [https://github.com/adamghill/django-unicorn/](https://github.com/adamghill/django-unicorn/)!

Unicorn photo by [Meritt Thomas](https://unsplash.com/@merittthomas?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/unicorn?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)