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

challenge icon

Défi

Moyen

Transforme task_detail en une classe TaskDetail(View) :

  • Les méthodes get, patch et delete, 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 nom task_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))
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