Django + Unpoly = ❤️

1st: 03 January 2023 • Last Updated: 07 October 2024 • 4 min read

Yeah, that’s is. Been there, done that.

First things first: I find VueJS and Svelte great frameworks. They provide a lot of “free” stuff to web development. Being “lot” my main issue here.

In order to make things work, these frameworks (include all other modern JS frameworks here) need a set of tools, knowledge, workflows etc. that, now, you have to deal with: eg. new build tools, front-end state management, async programming, JS programming - for that matter etc.

Don’t get me wrong, I see the value of all of that if (and it should be a big IF) your application need it. And, by “need it”, IMHO, your app should have bells and wistles that would make your user’s eyes pop-out of their heads.

For all the other web app development, I can’t see the real benefits: twice the work for not so much gain.

The kind of application I build are, mostly, CRUDs with strong logic validations and a lot of integrations. UI on those apps are quite simple and don’t have that kind of interactivity to justify so much work.

As I was looking around to “solve” that “problem” I found htmx. Oh boy. It was a nice vision: no JS builds, no JWTs messing around, plain old server-side technology (Django, of course) and, still, a user facing app that feels like an SPA. Though htmx is great, I felt like I still had to do too much to make things with a nice touch.

From Carlson (htmx creator), I heard about Unpoly. And, oh boy x2, I was happy.

Unpoly is a one-js-file framework that can handle a lot. Its based on the concept of being less intrusive and transparent to the already existing devlopment workflow. For that, it uses a technique of making Ajax calls to the server (it is server technology agnostic), receive the old-style html page, extract element (or elements) you informed of that page and replace them in the page that is already rendered in the browser.

Another really nice concept are Layers. These are modal views (Unpoly handles the JS for that) that are forks of the main user interaction. Once a layer is opened, every other user interaction is targetted to that layer, by design. Imagine a To-do app. To create a new to-do, you could ask Unpoly to open a new layer with the new to-do form and once the user clicks “Add To-do”, the layer would close and refresh the todo list behind it. The snippet bellow is 90% of what I described:

<a class="btn btn-primary"
   href="{% url 'new-todo' %}"
   up-layer="new"
   up-accept-location="{% url 'todo-home' %}"
   up-on-accepted="up.reload('#todo-list')">
</a>
  1. up-layer="new" - opens a new layer with the new to-do form (the url part asks for the form page)
  2. up-accept-location - is responsible for closing the layer if the URL of the browser changes to something like the URL I’m informing (in this case the to-do home screen with the to-do’s list
  3. up-on-accepted - the the responsible for reload the to-do’s list element with the HTML id="#todo-lists"

And that’s all to it. All your backend code stays the same. If you would render the new to-do form as a new page with a full page reload of the browser, keep doing it. Unpoly intercepts that and change this behaviour.

There’s a nice demo on Unpoly’s site. Worth taking a look.

I’m very exited to be using it. My productivity is through the roof since Django is already a very productive backend framework (“The web framework for perfectionists with deadlines”) and I don’t have to deal with a whole new front-end language, tools pipelines and whatnot.