Erreurs de validation JSON
Fait partie de la section API JSON du Journey Django de Coddy. Leçon 7 sur 19.
Actuellement, une requête POST sans titre provoque une erreur KeyError, et Django répond Erreur serveur 500, ce qui n’indique pas au programme ce qu’il faut corriger.
Lorsque le problème vient des données, répondez 400 Requête incorrecte et indiquez ce qui ne va pas au format JSON, avec un message par champ, comme un formulaire Django conserve ses erreurs. Une librairie qui vérifie l’année d’un livre :
errors = {}
year = data.get("year")
if not isinstance(year, int) or year < 0:
errors["year"] = "Enter the year as a whole number."
if errors:
return JsonResponse({"errors": errors}, status=400)Deux pièges subsistent. Un titre composé uniquement d’espaces n’est pas vide, mais " ".strip() vaut "". Et un corps qui n’est pas au format JSON fait lever à json.loads une exception json.JSONDecodeError, que try et except transforment en réponse 400. Un statut 4xx signifie que l’appelant a envoyé quelque chose d’incorrect ; un statut 5xx signifie que votre code a échoué.
Défi
MoyenFaites en sorte que POST /api/tasks/ renvoie 400 lorsque les données sont incorrectes :
- Aucun titre, ou uniquement des espaces :
{"errors": {"title": "This field is required."}}, et rien n’est enregistré. - Un corps qui n’est pas du JSON :
{"error": "The body is not valid JSON."}. - Un titre valide est enregistré sans les espaces qui l’entourent.
Appuyez sur Run, puis dans l’onglet Shell : from django.test import Client; print(Client().post("/api/tasks/", {"title": " "}, content_type="application/json").json())
Essayez vous-même
import json
from django.http import JsonResponse
from django.shortcuts import render
from django.views.decorators.csrf import csrf_exempt
from .models import Task
def task_to_dict(task):
return {
"id": task.id,
"title": task.title,
"done": task.done,
"priority": task.priority,
}
def home(request):
return render(request, "tasks/home.html", {"tasks": Task.objects.all()})
def stats(request):
data = {
"total": Task.objects.count(),
"done": Task.objects.filter(done=True).count(),
}
return JsonResponse(data)
@csrf_exempt
def task_list(request):
if request.method == "POST":
data = json.loads(request.body)
task = Task.objects.create(
title=data["title"],
priority=data.get("priority", "normal"),
)
return JsonResponse(task_to_dict(task), status=201)
tasks = Task.objects.all()
done = request.GET.get("done")
if done == "true":
tasks = tasks.filter(done=True)
elif done == "false":
tasks = tasks.filter(done=False)
return JsonResponse([task_to_dict(task) for task in tasks], safe=False)
def task_detail(request, pk):
task = Task.objects.filter(pk=pk).first()
if task is None:
return JsonResponse({"error": "Task not found"}, status=404)
return JsonResponse(task_to_dict(task))
Toutes les leçons de API JSON
2Lire les requêtes
Filtrer avec une requêteCréer avec POST5Projet : Trier le travail
Projet : Les prioritésProjet : Effacer les tâches terminéesEntraînez-vous par vous-même : Playground Django