DEV Community

Pedro Campos
Pedro Campos

Posted on • Edited on

Django project - Part 4 HTMX, TailwindCSS and AlpineJS

Introduction

Now is the fun part, add HTMX, TailwindCSS, AlpineJS and change the home page to test the three libs.

The source code from this part

Tailwind

We are going to install the Tailwind through the container instance and then add the generated the json files to the Dockerfile, so it will be installed on the next build. This is made only once.

# install npm on image
RUN apk add --no-cache npm
Enter fullscreen mode Exit fullscreen mode

Enter on the container to install Taiwind. let's add a just command to help in the future
justfile:

...
# Enter in the container shell
shell:
  docker compose run --rm web sh
Enter fullscreen mode Exit fullscreen mode

Execute the command
$ just shell
Enter on the container to install Taiwind. let's add a just command to help in the future
justfile:

# npm install -D tailwindcss
# npx tailwindcss init
Enter fullscreen mode Exit fullscreen mode

That will create 3 files: package.json, package-lock.json and tailwind.config.js. Let's add them to the Dockerfile and rebuild the container, except the tailwind.config.js, which will be added with the rest of the code.

...
# install npm on image
RUN apk add --no-cache npm

# tailwind stuff
COPY package*.json ./
# use the json to install the Tailwind
RUN npm install
...
Enter fullscreen mode Exit fullscreen mode

Create the file palindrome/static/css/input.css

@tailwind base;
@tailwind components;
@tailwind utilities;
Enter fullscreen mode Exit fullscreen mode

and config the tailwind.config.js:

/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
    "./palindrome/templates/**/*.{html,js}",
    "./palindrome/static/**/*.{html,js}",
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}
Enter fullscreen mode Exit fullscreen mode
Add STATICFILES_DIRS to the settings.py to reflect the custom directory.
Enter fullscreen mode Exit fullscreen mode
...
STATICFILES_DIRS = [BASE_DIR / 'palindrome/static']

Enter fullscreen mode Exit fullscreen mode

Now we need to add the tailwind start on the start script, on docker/dev/start:

# -i the input.css for some tailwind directives or pure css, it will be added to the -o output.css in the
# tailwind processing, --watch=always is the hot reload.
echo "Starting tailwindcss watcher"
exec npx tailwindcss -i ./palindrome/static/css/input.css -o ./palindrome/static/css/output.css --watch=always &


Enter fullscreen mode Exit fullscreen mode

You can add a tailwind tag to a header, in the palindrome/templates/base/home.html, to test the configuration:

<head>
    ...
    <!-- Tailwind output file -->
    <link
            href="{% static 'css/output.css' %}"
            rel="stylesheet">
    ...
</head>
...

<h1>Simple Header</h1>  
<h1 class="text-3xl font-bold underline p-10">Simple Tailwind header</h1>  
<hr>

...
Enter fullscreen mode Exit fullscreen mode

AlpineJS

AlpineJS it's very simple, just download the lib and add to the page.

Go to the alpine.dev, download the lib cdn.mim.js in the palindrome/static/css and change the name to alpine.min.js . Should be something like this:

$ wget https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js
$ mv cdn.min.js alpine.min.js
Enter fullscreen mode Exit fullscreen mode

Add to the home header and write a test code.

{% load static %}
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta
            name="viewport"
            content="width=device-width, initial-scale=1.0">
    <!-- Tailwind output file -->
    <link
            href="{% static 'css/output.css' %}"
            rel="stylesheet">
    <script
            src="{% static 'js/alpine.min.js' %}"
            defer></script>
    <title>Title</title>
</head>
<body>
<h1>Simple Header</h1>
<h1 class="text-3xl font-bold underline p-10">Simple Tailwind header</h1>
<hr>
<h1 class="text-3xl font-bold underline pt-10 px-10">Simple AlpineJS counter</h1>
<div x-data="{ count: 0 }"
     class="text-3xl font-bold underline pb-10 px-10">
    <button x-on:click="count++">Increment</button>

    <span x-text="count"></span>
</div>
<hr>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

Now you have an increment button to test the Alpine configuration

HTMX

Almost as easy as the AlpineJS, but with a little more work.
Download the HTMX lib from HTMX website in the palindrome/static/js folder:

$ wget https://unpkg.com/browse/htmx.org@2.0.3/dist/htmx.min.js
Enter fullscreen mode Exit fullscreen mode

Install an extension for django, the django-htmx, it has a Middleware that provides a request.htmx, which in used in htmx partial views.
Create a View on the base/view.py to respond to the HTMX call from the browser.

from django.http import HttpResponse

...

def htmx(request):  
    """  
    A simple htmx view that return a partial html.    
    """    
    return HttpResponse('<span id="click-test">HTMX is working</span>')
Enter fullscreen mode Exit fullscreen mode

Add the View in the url.py

from django.urls import path

from palindrome.base.views import HomeView, htmx

app_name = 'base'
urlpatterns = [
    path('', HomeView.as_view(), name='home'),
    path('htmx/', htmx, name='htmx'),
]

Enter fullscreen mode Exit fullscreen mode

Create a HTMX call from the home.html.

{% load static %}  
<html lang="en">  
<head>  
   ...
    <script            
            src="{% static 'js/htmx.min.js' %}"  
            defer></script>  
    <title>Title</title>  
</head>  
<body>  
...
<hr>  
<h1 class="text-3xl font-bold underline pt-10 px-10">Simple HTMX</h1>  
<div class="flex flex-row">  
    <button class="bg-blue-500 hover:bg-blue-700 text-white font-bold  
        py-2 px-4 mb-10 mx-10 rounded w-fit"            
            hx-get="{% url 'base:htmx' %}"  
            hx-trigger="click"  
            hx-target="#click-test"  
            hx-swap="outerHTML"  
    >  
        Click Me!  
    </button>  
    <span id="click-test"></span>  
</div>  
</body>  
</html>
Enter fullscreen mode Exit fullscreen mode

Wraping up

Add /node_modules/ to the .gitignore.
prepare for commit:

$ just format
$ git add .
$ git commit -m 'nice description'

Enter fullscreen mode Exit fullscreen mode

Top comments (0)