Menu
CoddyTech

Une classe par ressource

Fait partie de la section API JSON du Journey Django de Coddy. Leçon 11 sur 19.

task_detail est maintenant une chaîne de blocs if request.method == ..., accompagnée d’une liste de méthodes à tenir à jour en parallèle. La classe de base de Django, View, dont héritent toutes les vues génériques que tu as utilisées, se charge de cette gestion.

Ajoute à la classe une méthode par méthode HTTP, nommée en minuscules. View appelle celle qui porte le nom correspondant à la requête et répond avec 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(). Ici, la ressource est le thème de couleur d’un visiteur, conservé dans la session :

from django.utils.decorators import method_decorator
from django.views import View

@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.

challenge icon

Défi

Moyen

Transforme task_detail en classe.

  1. Dans tasks/views.py, importe View depuis django.views et method_decorator depuis django.utils.decorators.
  2. Remplace la fonction et les deux décorateurs par class TaskDetail(View). Ses méthodes get, patch et delete prennent (self, request, pk) et chacune effectue le travail de son ancienne branche.
  3. Exempte la classe de la protection CSRF en appliquant method_decorator(csrf_exempt) à dispatch.
  4. Dans tasks/urls.py, dirige la route vers views.TaskDetail.as_view(), en conservant le nom task_detail.

Ouvre /api/tasks/1/ : Buy milk s’affiche au format JSON.

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))
quiz iconTestez-vous

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