How to Escape the Tyranny of Complicated Javascript in 4 Easy Steps
Tags: python, django, javascript, unicorn
Published: 2020-08-28 02:14:55

---
title: How to Escape the Tyranny of Complicated Javascript in 4 Easy Steps
published: true
description: How django-unicorn, the magical fullstack framework for Django, was created
tags: python, django, javascript, unicorn
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/i0oy6ganho3zhcl5q2ny.jpg
series: django-unicorn
---

The internet is full of people telling you how to do complicated things, but I'm always more interested in how to simplify web development. `django-unicorn` is my attempt at reducing the context switches between Python and Javascript and writing unnecessary code just for simple interactivity on a website.

My goal is for you to continue to use Django and all of its wonderful tools to build server-side websites, and then sprinkle a little magic on top to enable interactivity without jumping to a more complicated frontend framework. See [Add Some Magic to Your Django Website - DEV](https://dev.to/adamghill/add-some-magic-to-your-django-website-l8k) for more reasons to use `django-unicorn`, or go to [django-unicorn.com](https://www.django-unicorn.com) to read the documentation. However, this article will detail, at a high level, how `django-unicorn` works.

The basic flow of `django-unicorn`:

1. A Django template tag includes the component's HTML. It also bootstraps the component's `unicorn:model`s with initial values based on the component class.
  
2. Javascript that listens to events on the component and calls a dedicated API endpoint with specific JSON based on the user interactions.
  
3. A Django view that parses the JSON. Depending on the JSON, it will perform an action on a newly instantiated component class. The component class then re-renders itself and returns the new HTML.
  
4. Javascript then takes the newly re-rendered component and uses [morphdom](https://github.com/patrick-steele-idem/morphdom) to intelligently "merge" the new HTML from the re-rendered component into the old HTML.


## The Bootstrap

The magic all starts with a few Django [template tags](https://docs.djangoproject.com/en/stable/howto/custom-template-tags/). The first, `{% unicorn_scripts %}` loads the required Javascript onto the page. The second, `{% unicorn %}` is used to include the specified component.

```html
{% load unicorn %}

<!DOCTYPE html>
<html lang="en">

    <body>
        {% csrf_token %}
        {% unicorn_scripts %}

        {% unicorn 'hello-world' %}
    </body>
</html>
```

With an initial `django-unicorn` component, the `{% unicorn %}` template tag is very similar to the regular [include](https://docs.djangoproject.com/en/stable/ref/templates/builtins/#include) template tag. Based on conventions built into `django-unicorn`, it looks in `unicorn\template\` for a HTML template named `hello-world.html` and in `unicorn\components\` for a component module named `hello_world.py` and a `UnicornView ` class named `HelloWorld`.

All public properties and methods found in the component class are registered to be used by the HTML template. Properties and their values are exposed as a JSON object along with a Javascript method call to initialize the component's frontend code. A unique component id and a security checksum based on the initial data are also generated.

## Javascript initialization

The initialized Javascript then gets all HTML elements with a `unicorn:` attribute. If the attribute is `unicorn:model` than an event listener is attached that fires for `input` or `blur` events. Otherwise, whatever occurs after `unicorn:` is used as the event that is listened to. For example, `unicorn:click` will listen for `click` events. Based on the event fired, JSON is created to tell the API endpoint to either update a component's property or call a method on the component. Then, the Javascript POSTs the generated JSON to the API endpoint.

## Message endpoint

First, the checksum is first inspected to make sure that the data hasn't been tampered with. Along with the CSRF token passed along with the POST, these prevent a malicious user from changing the data the comes from the frontend.

Next, a new component is instantiated and properties are set or methods are called as specified by the JSON. Then, the component is re-rendered with the new context data. Then new HTML, along with some housekeeping data, is sent back in a JSON response.

## Javascript DOM magic

The endpoint response's new component HTML gets magically merged into the old component HTML with `morphdom`. Then, form elements are set based on the component class.


`django-unicorn` is currently at version 0.5.0 and works pretty well for simple use-cases, but there is still a ton to do to provide a complete framework to reduce complexity and simplify creating a Django website in the future. I would really appreciate any feedback, [GitHub issues](https://github.com/adamghill/django-unicorn/issues), or PRs to help add a little bit of magic back into creating a website.

Unicorn photo by [Wilmer Martinez](href="https://unsplash.com/@wilmerlens?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText") on [Unsplash](https://unsplash.com/s/photos/unicorn?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText)