Response de DRF vs JsonResponse de Django : Comprendre ce que nous utilisons « sans y penser »

Comme la plupart des développeurs Django, j'utilise presque toujours (99% du temps) le package DRF ([[Django REST Framework]]) dans mes projets [[Django]].

De ce fait, lorsque je renvoie une réponse au serveur, qu'il s'agisse d'une réponse d'API ou d'une simple requête JSON provenant d'un template, j'utilise la classe de réponse structurée Response sans me poser de questions. Vraiment, je l'utilise sans y penser.

C'est parce qu'elle s'intègre parfaitement avec les sérialiseurs, et qu'en utilisant cette classe Response par défaut pour toutes les réponses, je n'ai pas à me soucier de quoi que ce soit.

Mais aujourd'hui, une question m'a soudainement traversé l'esprit : « Au fait, en quoi la classe Response diffère-t-elle de django.http.JsonResponse, et dans quelle mesure ? » J'ai donc décidé de tenter de résoudre ce mystère aujourd'hui.


1. Des origines différentes : Statique ou Flexible ?

Diagramme des différences entre JsonResponse et Response

En examinant l'ascendance de ces deux classes, j'ai découvert des différences intéressantes.

  • JsonResponse : Hérite de HttpResponse de Django. Son objectif est très clair : « Recevoir des données, les sérialiser avec json.dumps(), puis les envoyer avec un Content-Type fixé à application/json. » C'est tout. C'est une classe simple et intuitive.

  • DRF Response : Elle hérite de SimpleTemplateResponse. Hmm ? Qu'est-ce que c'est ? Pourquoi hériter d'une classe liée aux templates ? C'est là que la véritable nature de Response se révèle. Cette classe que j'utilisais sans y penser était en fait un « conteneur de données avant le rendu », ne pré-déterminant pas le résultat final !!


2. La différence clé : La Négociation de Contenu (Content Negotiation)

Alors que JsonResponse adopte une approche « Je suis du JSON, un point c'est tout ! », la classe Response de DRF est très flexible et intelligente.

La Response de DRF demande au client ce qu'il souhaite. (C'est ce qu'on appelle la Négociation de Contenu). Si le client envoie Accept: text/html dans l'en-tête, elle affiche l'interface « Browsable API » que nous connaissons bien ; si le client envoie Accept: application/json, elle renvoie uniquement des données JSON pures.

En d'autres termes, la classe Response elle-même ne fait que contenir les données, et ce sont les Renderers de DRF qui décident de la forme sous laquelle elles seront présentées. Si nous pouvions utiliser Response sans y réfléchir et obtenir la réponse appropriée, c'était grâce au travail acharné de négociation effectué en arrière-plan par DRF.

Ce fut une découverte et une prise de conscience absolument étonnantes. Je me suis dit que c'était vraiment un outil conçu avec une grande minutie. À de tels moments, je ressens une brève gratitude envers les développeurs et contributeurs de Django/DRF.


3. La facilité de Sérialisation

Lorsque vous utilisez JsonResponse, vous devez « affiner » manuellement vos données sous forme de dictionnaires ou de listes Python. En revanche, Response s'accorde parfaitement avec les Serializers de DRF.

Voyons un exemple simple. Que se passerait-il si vous deviez renvoyer les informations d'un article de blog ?

Cas A : JsonResponse (version manuelle fastidieuse)

from django.http import JsonResponse
def post_detail(request, pk):
    post = Post.objects.get(pk=pk)
    # Il faut créer manuellement un dictionnaire pour chaque donnée.
    # Si vous avez 20 champs ? Hmm... ce serait plutôt agaçant.
    data = {
        "title": post.title,
        "content": post.content,
        "created_at": post.created_at.strftime("%Y-%m-%d"), # Le format de date aussi, manuellement !
    }
    return JsonResponse(data)

Cas B : DRF Response (version automatisée)

from rest_framework.response import Response
from rest_framework.decorators import api_view

@api_view(['GET'])
def post_detail(request, pk):
    post = Post.objects.get(pk=pk)
    serializer = PostSerializer(post)

    # Il suffit de renvoyer directement .data.
    # Les relations complexes (Foreign Key) ou le formatage des dates sont gérés automatiquement par le sérialiseur.
    return Response(serializer.data)

Vous voyez la différence ? Avec JsonResponse, nous devons préparer les ingrédients et les disposer nous-mêmes sur l'assiette. En revanche, avec Response, il suffit de passer des instances de modèles complexes ou des QuerySets à un « robot culinaire » appelé sérialiseur, puis de renvoyer le résultat tel quel. Le renderer se charge ensuite de le transformer joliment en une chaîne JSON finale.

En travaillant parfois avec des IA méticuleuses comme ChatGPT, j'ai remarqué à plusieurs reprises qu'elles créaient manuellement les données de réponse avant d'appeler Response pour les renvoyer, par excès de zèle ou par prudence excessive.

Les développeurs soucieux de l'efficacité peuvent se sentir un peu mal à l'aise face à un tel code. Dorénavant, si une IA génère un tel code, n'hésitez pas à le corriger.


Alors, devrions-nous continuer à utiliser Response même pour de simples réponses JSON ?

Bien que ma conclusion soit basée à 100% sur mon expérience subjective, ma réponse est : « Absolument aucun problème. C'est même recommandé. »

Techniquement parlant, Response passe par un processus de Négociation de Contenu et vérifie plusieurs renderers, ce qui peut entraîner un coût de calcul très légèrement supérieur à celui de JsonResponse. Cependant, cette différence est imperceptible sur les infrastructures modernes (même sur mon Raspberry Pi 5 !).

Au contraire, les avantages à continuer d'utiliser Response sont bien plus importants.

  1. Cohérence : Permet d'unifier le format des réponses sur l'ensemble du projet.
  2. Débogage : Facilite la vérification directe des données via l'API explorable (Browsable API) lors de l'accès depuis un navigateur.
  3. Flexibilité : Si vous devez étendre le format de réponse à XML ou YAML ultérieurement, cela peut être fait par simple configuration, sans modifier le code.

Conclusion : Connaître la différence est rafraîchissant

La conclusion de mon étude d'aujourd'hui est la suivante :

« En fin de compte, il n'y a pas de différence de performance majeure, et dans un environnement DRF, continuer à utiliser Response comme d'habitude est bénéfique pour la santé mentale. »

Cependant, je me sens rafraîchi d'avoir enfin compris comment l'outil que j'utilise quotidiennement fonctionne en interne, et pourquoi il est préférable d'utiliser une classe distincte comme Response plutôt que JsonResponse. Il semble qu'un développeur ne grandisse vraiment que lorsqu'il ne cesse de se poser la question « pourquoi ? ».

Maintenant que j'en connais la nature, je vais pouvoir utiliser Response avec une meilleure compréhension et plus d'assurance.


Si, comme moi, vous avez passé des nuits blanches à cause des subtiles différences entre Django et DRF, j'espère que cet article vous a été utile. N'hésitez pas à laisser vos questions ou commentaires ci-dessous !

Si vous avez trouvé cet article utile, n'hésitez pas à me suivre ! Pour cela, vous pouvez vous inscrire et créer un compte sur la Mikihands Blog Flatform. Écrire des articles de blog et savoir que quelqu'un les lit... c'est une expérience plutôt agréable.