Simplifier le développement web dynamique avec Django et HTMX (Partie 4) : Comment envoyer la charge utile (payload) ?
Dans les requêtes Ajax traditionnelles utilisant fetch en JavaScript, l'envoi d'une requête POST implique généralement la construction directe de la charge utile (payload) à l'aide de JSON.stringify().
Voici un exemple typique :
fetch("/api/todos/", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-CSRFToken": csrftoken
},
body: JSON.stringify({
title: "장보기",
done: false,
priority: 3
})
})
Mais qu'en est-il avec HTMX ? Comment hx-post transmet-il exactement les données au serveur ? De nombreux exemples se limitent à des fonctionnalités très simples, ce qui rend difficile la recherche d'exemples concrets pour l'envoi de charges utiles complexes.
Dans cet article, nous allons détailler les méthodes de transmission de données d'HTMX et la manière de les traiter côté serveur.

Les méthodes d'envoi de données avec HTMX
L'approche de fetch pour la charge utile et la méthode de transmission de données de hx-post sont assez différentes.
Avec fetch, le développeur construit directement l'objet et le convertit en JSON pour l'insérer dans le corps de la requête. HTMX, en revanche, collecte par défaut les valeurs présentes dans le DOM pour les envoyer.
La philosophie d'HTMX n'est pas de "construire directement des objets JS", mais plutôt de "collecter des valeurs à partir d'éléments HTML pour créer des paramètres de requête". Pour cela, il utilise généralement les trois méthodes suivantes :
1) Envoi de valeurs collectées via un formulaire
C'est l'approche la plus fidèle au HTML et qui s'intègre le mieux avec Django.
<form hx-post="/todos/create/" hx-target="#todo-list">
<input type="text" name="title" placeholder="제목">
<input type="number" name="priority" value="3">
<input type="hidden" name="done" value="false">
<button type="submit">등록</button>
</form>
Dans ce cas, HTMX collecte les valeurs des champs de saisie à l'intérieur du formulaire et les inclut dans la requête. L'encodage par défaut est le même que pour une soumission de formulaire classique : URL-encoded form data.
Dans une vue Django, vous pouvez les récupérer comme d'habitude :
def create_todo(request):
title = request.POST.get("title")
priority = request.POST.get("priority")
done = request.POST.get("done")
2) Inclure des valeurs d'autres éléments sans formulaire : hx-include
Cette méthode est utile lorsque vous souhaitez attacher hx-post à un seul bouton et inclure uniquement certaines valeurs d'entrée situées ailleurs dans le DOM.
<input type="text" id="title" name="title" placeholder="제목">
<input type="number" id="priority" name="priority" value="3">
<button hx-post="/todos/create/"
hx-include="#title, #priority"
hx-target="#todo-list">
등록
</button>
hx-include inclut les valeurs des éléments spécifiés dans la requête. Cela permet de créer un résultat similaire à une charge utile sans avoir à envelopper le tout dans un <form>, ce qui est très pratique pour un petit nombre de champs d'entrée.
3) Ajouter des valeurs cachées ou calculées : hx-vals
C'est la fonctionnalité qui se rapproche le plus de la création directe d'une partie de l'objet payload avec fetch.
<button hx-post="/todos/create/"
hx-vals='{"title": "장보기", "done": false, "priority": 3}'
hx-target="#todo-list">
빠른 등록
</button>
hx-vals ajoute des paramètres supplémentaires à la requête. Par défaut, il utilise la syntaxe JSON comme ci-dessus, mais en ajoutant le préfixe js:, vous pouvez également envoyer des valeurs calculées dynamiquement par JavaScript.
<input type="text" id="title" placeholder="제목">
<button hx-post="/todos/create/"
hx-vals='js:{title: document.querySelector("#title").value, done: false, priority: 3}'
hx-target="#todo-list">
등록
</button>
Dans ce cas également, Django lit les valeurs via request.POST. En effet, hx-vals sert à "définir des valeurs avec une syntaxe ressemblant à du JSON", et non à transformer le corps de la requête lui-même en JSON.
Attention : hx-vals est différent d'une "charge utile JSON"
C'est l'un des points les plus déroutants lorsque l'on débute avec HTMX.
<button hx-post="/my-url/" hx-vals='{"a":1, "b":2}'>
Ce code ne signifie pas "envoyer un objet JSON dans le corps de la requête", mais plutôt "ajouter a=1&b=2 aux paramètres de la requête". Autrement dit, le serveur doit toujours les traiter comme des données de formulaire.
Si vous souhaitez vraiment envoyer un corps de requête JSON
Si vous avez absolument besoin d'utiliser un format application/json, comme avec fetch(... JSON.stringify(payload)), alors l'extension json-enc d'HTMX est nécessaire.
Configurez-la comme suit, en vous référant à la documentation officielle :
<script src="https://unpkg.com/htmx.org@1.9.12/dist/ext/json-enc.js"></script>
<button hx-post="/api/todos/"
hx-ext="json-enc"
hx-vals='{"title": "장보기", "done": false, "priority": 3}'
hx-target="#result">
JSON으로 전송
</button>
C'est alors seulement que nous obtenons le format de charge utile JSON auquel nous sommes habitués. Dans ce cas, la vue Django recevra request.POST vide, et vous devrez lire request.body directement.
import json
def create_todo_api(request):
data = json.loads(request.body)
title = data.get("title")
# ... 로직 처리 ...
return JsonResponse({"ok": True})
HTMX et DRF : des philosophies différentes, mais pas forcément incompatibles
Bien qu'il soit possible d'envoyer du JSON avec une extension, la question demeure : est-ce la manière "HTMX" de faire les choses ? C'est là que deux philosophies entrent en conflit : celle "centrée sur les données (DRF)" et celle "centrée sur l'hypermedia (HTMX)".
Si vous décidez d'utiliser HTMX pleinement, il est peut-être nécessaire de vous éloigner temporairement de la pensée axée sur les données. Envoyer des valeurs avec <form>, hx-include, hx-vals et que le serveur reçoive ces données via request.POST pour renvoyer un snippet HTML plutôt que du JSON – c'est là qu'HTMX brille le plus.
Mais si les serializers de DRF sont trop précieux pour y renoncer ?
Les serializers de DRF sont incroyablement puissants. Faut-il les abandonner et se contenter de la méthode request.POST.get() si l'on utilise HTMX ?
Heureusement, les serializers de DRF sont également excellents pour valider les données de formulaire, pas seulement le JSON. Comme ce sujet serait trop long à aborder ici, nous explorerons en profondeur la "coexistence d'HTMX et des serializers DRF" dans le prochain article.
Conclusion
Voici un résumé des points clés abordés aujourd'hui :
- HTMX collecte par défaut les valeurs du DOM. Son approche est différente de
fetchqui construit directement l'objet de la charge utile. - Trois méthodes d'envoi : le
<form>pour l'ensemble,hx-includepour des éléments spécifiques, ethx-valspour ajouter des valeurs. - Le format par défaut est les données de formulaire. Attention, même si
hx-valsutilise une syntaxe JSON, cela ne signifie pas que le corps de la requête est envoyé en JSON. - Si le JSON est impératif, utilisez l'extension
json-enc. Cependant, il est bon de se rappeler que l'essence d'HTMX réside dans l'échange de fragments HTML.
La prochaine fois, nous verrons comment intégrer la commodité de DRF avec HTMX !
Articles associés
- Simplifier le développement web dynamique avec Django et HTMX (Partie 1)
- Simplifier le développement web dynamique avec Django et HTMX - Ajax (Partie 2)
- Simplifier le développement web dynamique avec Django et HTMX (Partie 3) : Intégration avec Django
- Simplifier le développement web dynamique avec Django et HTMX (Partie 4) : Les méthodes d'envoi de la charge utile (payload)
- Simplifier le développement web dynamique avec Django et HTMX : Utilisation des Forms et des Serializers
- Simplifier le développement web dynamique avec Django et HTMX : Maîtriser les déclencheurs