Une classe par ressource
Fait partie de la section API JSON du Journey Django de Coddy. Leçon 11 sur 19.
task_detail est désormais une chaîne de blocs if request.method == ... accompagnée d’une liste de méthodes qu’il faut maintenir en cohérence. La classe de base de Django, View, située sous toutes les vues génériques que vous avez utilisées, se charge de ce suivi.
Donnez à la classe une méthode par méthode HTTP, avec un nom en minuscules. View appelle celle qui porte le nom de la requête et renvoie le code 405 pour toute autre méthode. Les valeurs de l’URL arrivent après request, comme dans une vue fonctionnelle, et la route utilise .as_view(). Le thème de couleur d’un visiteur sous forme de ressource :
@method_decorator(csrf_exempt, name="dispatch")
class Theme(View):
def get(self, request):
return JsonResponse({"theme": request.session.get("theme", "light")})
def put(self, request):
data = json.loads(request.body)
request.session["theme"] = data["theme"]
return JsonResponse({"theme": data["theme"]})@csrf_exempt fonctionne sur les fonctions. Sur une classe, method_decorator l’applique à dispatch, la méthode par laquelle passe chaque requête.
Défi
MoyenTransforme task_detail en une classe TaskDetail(View) :
- Les méthodes
get,patchetdelete, qui font chacune ce que faisait la fonction, y compris la réponse 404. - Exempte-la de la protection CSRF avec
method_decorator. - La route utilise
views.TaskDetail.as_view()et conserve le nomtask_detail.
Clique sur Run, puis ouvre /api/tasks/1/ : la tâche s’affiche comme avant.
Essayez vous-même
import json
from django.http import HttpResponse, 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)
@csrf_exempt
@require_http_methods(["GET", "PATCH", "DELETE"])
def task_detail(request, pk):
task = Task.objects.filter(pk=pk).first()
if task is None:
return JsonResponse({"error": "Task not found"}, status=404)
if request.method == "DELETE":
task.delete()
return HttpResponse(status=204)
if request.method == "PATCH":
data = json.loads(request.body)
if "title" in data:
task.title = data["title"]
if "done" in data:
task.done = data["done"]
task.save()
return JsonResponse(task_to_dict(task))
Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Toutes les leçons de API JSON
Entraînez-vous par vous-même : Playground Django