Menu
CoddyTech

Projet : Les priorités

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

Il est temps d’ajouter une fonctionnalité par toi-même. Chaque tâche a une priority : low, normal ou high. L’API doit permettre aux programmes de demander une priorité et empêcher quiconque d’en inventer une quatrième.

Tu as déjà tous les éléments : request.GET.get() pour un filtre, un QuerySet que tu peux filtrer plusieurs fois et le dictionnaire errors que tu renvoies avec le code 400.

Les valeurs autorisées sont définies sur le modèle. Task.Priority est une classe TextChoices, et Task.Priority.values est la liste ["low", "normal", "high"]. Vérifier que la priorité figure dans cette liste signifie qu’une priorité ajoutée ultérieurement au modèle sera acceptée sans modification de la vue.

challenge icon

Défi

Moyen

Dans task_list de tasks/views.py, ajoute des priorités. ?priority=high affiche uniquement les tâches de priorité élevée et fonctionne aussi avec ?done= : ?priority=high&done=false. Une requête POST avec une priorité autre que low, normal ou high n’enregistre rien et renvoie 400 avec le message dans le dictionnaire d’erreurs, comme dans {"errors": {"priority": "Choose low, normal or high."}}. En l’absence de priorité, la valeur reste normal.

Clique sur « Jouer » : l’aperçu ouvre /api/tasks/?priority=high et affiche Write the report.

Essayez vous-même

import json

from django.http import HttpResponse, JsonResponse
from django.shortcuts import get_object_or_404, render
from django.utils.decorators import method_decorator
from django.views import View
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")


def task_page(request):
    return render(request, "tasks/list.html", {"tasks": Task.objects.all()})


def task_row(request, pk):
    task = get_object_or_404(Task, pk=pk)
    return render(request, "tasks/list.html#task-row", {"task": task})


@require_GET
def stats(request):
    total = Task.objects.count()
    done = Task.objects.filter(done=True).count()
    data = {
        "total": total,
        "done": done,
        "open": total - done,
    }
    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)


def not_found():
    return JsonResponse({"error": "Task not found"}, status=404)


@method_decorator(csrf_exempt, name="dispatch")
class TaskDetail(View):
    def get(self, request, pk):
        task = Task.objects.filter(pk=pk).first()
        if task is None:
            return not_found()
        return JsonResponse(task_to_dict(task))

    def patch(self, request, pk):
        task = Task.objects.filter(pk=pk).first()
        if task is None:
            return not_found()
        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))

    def delete(self, request, pk):
        task = Task.objects.filter(pk=pk).first()
        if task is None:
            return not_found()
        task.delete()
        return HttpResponse(status=204)

Toutes les leçons de API JSON

Entraînez-vous par vous-même : Playground Django