2024-02-05 Django REST Framework and Vue versus Django and HTMX by Špela Giacomelli

Špela Giacomelli

GirlThatLovesToCode is passionate about learning new things – both for herself and for teaching others.

She’s a fan of Python and Django and wants to know everything there is about those two. When she’s not writing code or a blog, she’s probably trying something new, reading, or spending time outside with her family.

Introduction

This article details the differences between developing an application with Vue and Django REST Framework (DRF) versus HTMX and Django.

We’ll look into a simple example of how both combinations work and compare their strengths and weaknesses.

HTMX and Django

../../../../_images/htmx_2023.webp

HTMX has a reputation of a being “JavaScript framework for people who hate JavaScript”.

It’s rapidly gaining popularity due to its lightweight and ease of use.

If you’ve used any frontend framework before, it has an entirely different feeling to it – it’s less a framework and more of HTML on steroids.

When using HTMX, you can easily achieve dynamic page rendering just by using a handful of HTMX-specific attributes directly in HTML.

The core attributes allow you to set an HTTP method and URL for the request (e.g., hx-put), set what event is going to trigger it (hx-trigger), and set the element that’s going to be altered with the response (hx-target).

The easiest way to work with HTMX and Django is to heavily intertwine them.

Unlike the Vue and DRF pairing, where each framework can be swapped out independently, you can’t just unplug Django or HTMX and replace it with something else (at least not easily).

On the one hand, the Django code intended for HTMX interactions differs from regular Django code. Conversely, HTMX is embedded directly within Django templates, not existing as separate files. Once you decide to use that combination, replacing either tool with something else would require a complete rewrite.

On the other hand, using plain Django and deciding you need a little more interactivity along the way poses no problem for the lightweight HTMX. Your whole project could rely solely on Django, and adding a single HTMX functionality after a few months would require little overhead.

Let’s see what accomplishing the same thing – a simple password generator with Django and HTMX – looks like.

HTMX is simply included in Django, meaning there are no specific HTMX files. Views and URLs look exactly like you’re used to in plain Django:

# views
class GeneratePasswordPage(TemplateView):
    template_name = "generate_password_page.html"


class GeneratePassword(APIView):
    def get(self, request):
        password = "".join(
            secrets.choice(string.ascii_letters + string.digits + string.punctuation)
            for _ in range(12)
        )
        return Response(password)


# URLs
urlpatterns = [
    path("password/", views.GeneratePasswordPage.as_view(), name="generate_password_page"),
    path("password/generate", views.GeneratePasswordPartial.as_view(), name="generate_password_partial")
]

The template is a typical Django template with a bit of HTMX sprinkled in:

{% extends 'base.html' %}

{% block content %}
  <p id="password">{{ password }}</p>
  <br>
  <button hx-get="{% url 'generate_password_partial' %}"
          hx-target="#password"
  >
    Generate a password
  </button>
{% endblock %}

As you can see, the template is simpler than the Vue counterpart.

It almost completely relies on Django – HTMX sends the request and includes the response in the HTML.

HTMX does not have built-in state management; it fully depends on the backend (Django, in our case) to manage the state.

In this case, Django provides two endpoints because, unlike the Vue case where Vue manages the initial page, here it’s Django that’s responsible for serving the initial page.

When the button is clicked, the request is made to the second endpoint.

That endpoint returns a response with a password. That password is then included in the page by HTMX.

In contrast to plain Django, combining it with HTMX requires a lot of fragmented Django views . Using HTMX to achieve a Vue-like app with many changeable components can quickly become hard to manage.

HTMX versus Vue

It’s important to understand that directly comparing HTMX and Vue is like comparing apples and oranges. They address entirely different aspects of web development.

HTMX focuses on server-driven interactions, passing the data to the server and updating the page based on its response. Vue’s primary purpose is to build and manage dynamic user interfaces on the client side. This main difference ripples through every aspect of the development process.

One of the most significant differences between HTMX and Vue is how they manage state. HTMX is stateless and relies on the server side for state management, while Vue handles state right in the browser, which is crucial for creating more dynamic user experiences.

HTMX is undoubtedly less complex – it’s an enhancement for HTML and Vue is a fully-fledged frontend framework. While adding Vue to an existing project is easier than, let’s say, React, it’s still more complicated than adding HTMX. However, Vue’s design keeps that complexity manageable, even when you scale up your project.

HTMX, while straightforward for small additions, can get trickier with larger, more complex implementations.

No matter which option you choose, it’s unlikely to be the only tool you’ll need.

Vue has a rich ecosystem, offering integrations with CSS frameworks, routing, state management, and more. There’s even a browser dev tool to aid in development.

HTMX offers a handful of extensions and can be complemented by other third-party tools, yet it lacks official integration options. While commonly paired with tools such as Alpine.js and Tailwind CSS, these remain separate, without a dedicated integration tool to seamlessly connect them.

When deciding which framework to use, two aspects that often get overlooked are testing and deployment.

Having two separate projects requires two development environments and a different approach to testing.

Vue can be tested either in isolation, where you need to mock backend responses, or with actual responses from backend, in which case you’d need a dedicated testing environment. Tests with a real API tend to be slower and more flaky but closer to reality.

HTMX, when added to Django, can be mostly tested using Django’s testing tools and supplemented with something like Cypress for the most critical user flows.

Regarding deployment, when using DRF/Vue, the most common option is to deploy them separately – e.g., two Docker containers. Then you need to either serve them from different domains and set up CORS headers or deploy them behind a path-based proxy – e.g., route all requests starting with the /api/ prefix to the DRF container; the rest goes to Vue – on the same domain.

In such case, you also need to handle what can be accessed/shown to authenticated/unauthenticated users on both ends – e.g., block API requests for unauthenticated users, redirect to the login page inside Vue when the API rejects the request as unauthenticated.

While this might sound like a lot of overhead, it makes perfect sense when you need to build client-rich applications or when you have different clients.

For example, if you need to build an API for an iOS app, you might as well just reuse it for your web Vue app.

Conclusion

This article offered insights into the differences between developing an application with Vue and Django REST Framework (DRF) versus HTMX and Django.

Depending on your needs and preferences, you can now make a more informed decision on which combo to use.

The choice between Vue with Django REST Framework and HTMX with Django depends on your project’s specific requirements and goals as well as your development team’s expertise.

If you decide that HTMX suits you needs best, you can learn in detail how to combine Django and HTMX in our Full-stack Django with HTMX and Tailwind course.

If you decide that your project requires a separate front and back-end, we’ve got you covered as well: