Menu
CoddyTech

Una classe per risorsa

Fa parte della sezione API JSON del percorso Django di Coddy. Lezione 11 di 19.

task_detail ora è una catena di blocchi if request.method == ... più un elenco di metodi da mantenere sincronizzato con essi. La classe base di Django View, su cui si basano tutte le viste generiche che hai usato, si occupa di questa gestione.

Assegna alla classe un metodo per ogni metodo HTTP, con il nome in minuscolo. View chiama quello che porta il nome della richiesta e risponde con 405 a qualsiasi altra. I valori provenienti dall'URL arrivano dopo request, come in una vista basata su funzione, e la route usa .as_view(). Qui la risorsa è il tema di colore di un visitatore, conservato nella sessione:

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 funziona con le funzioni. Su una classe, method_decorator lo applica a dispatch, il metodo attraversato da ogni richiesta.

challenge icon

Sfida

Medio

Trasforma task_detail in una classe.

  1. In tasks/views.py, importa View da django.views e method_decorator da django.utils.decorators.
  2. Sostituisci la funzione e i due decoratori con class TaskDetail(View). I suoi metodi get, patch e delete accettano (self, request, pk) e ciascuno esegue il lavoro del ramo corrispondente di prima.
  3. Esenta la classe dalla protezione CSRF applicando method_decorator(csrf_exempt) a dispatch.
  4. In tasks/urls.py, instrada verso views.TaskDetail.as_view(), mantenendo il nome task_detail.

Apri /api/tasks/1/: Buy milk viene mostrato come JSON.

Provalo tu

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 iconMettiti alla prova

Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.

Tutte le lezioni di API JSON

Esercitati da solo: Playground Django