Modifier avec PATCH
Fait partie de la section API JSON du Journey Django de Coddy. Leçon 9 sur 19.
Un programme marque une tâche comme terminée en envoyant {"done": true} à l’URL de la tâche, et rien d’autre. Cette URL désigne la tâche elle-même, une ressource, et la méthode indique quoi en faire : GET la lit, PATCH en modifie une partie. Sa méthode sœur, PUT, remplace toute la ressource.
Une vue PATCH ne modifie donc que les champs présents dans le corps de la requête. Une valeur par défaut est le piège. Dans une API de librairie :
book.title = data.get("title", "")Un programme qui envoie uniquement {"available": false} efface le titre. Vérifie d’abord si la clé a été envoyée : "title" in data vaut True uniquement dans ce cas. Définis chaque champ présent, enregistre une seule fois et renvoie l’objet modifié. La vue a besoin de @csrf_exempt et de la nouvelle méthode dans require_http_methods, comme c’est le cas pour task_list.
Défi
MoyenPermettez aux programmes de modifier une tâche avec PATCH /api/tasks/<id>/ :
task_detailaccepteGETetPATCH, et est décorée par@csrf_exempt.- PATCH définit
titleetdoneuniquement si le corps de la requête les contient, enregistre la tâche et renvoie celle-ci. - Si la tâche est introuvable, la réponse reste 404.
Cliquez sur Run, puis dans l’onglet Shell : from django.test import Client; print(Client().patch("/api/tasks/1/", {"done": True}, 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 django.views.decorators.http import require_GET, require_http_methods
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()})
@require_GET
def stats(request):
data = {
"total": Task.objects.count(),
"done": Task.objects.filter(done=True).count(),
}
return JsonResponse(data)
@csrf_exempt
@require_http_methods(["GET", "POST"])
def task_list(request):
if request.method == "POST":
try:
data = json.loads(request.body)
except json.JSONDecodeError:
return JsonResponse({"error": "The body is not valid JSON."}, status=400)
errors = {}
title = data.get("title", "").strip()
if not title:
errors["title"] = "This field is required."
if errors:
return JsonResponse({"errors": errors}, status=400)
task = Task.objects.create(
title=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)
@require_GET
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
Entraînez-vous par vous-même : Playground Django