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. La classe base di Django View, alla base di ogni vista generica 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 prende il nome dalla richiesta e risponde con 405 per qualsiasi altro metodo. I valori dall’URL arrivano dopo request, come in una vista funzione, e la route usa .as_view(). Il tema cromatico di un visitatore come risorsa:

@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 sulle 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 TaskDetail(View):

  • Metodi get, patch e delete, ognuno dei quali fa ciò che faceva la funzione, incluso il 404.
  • Esentala dalla protezione CSRF con method_decorator.
  • La route usa views.TaskDetail.as_view(), mantenendo il nome task_detail.

Premi Run, poi apri /api/tasks/1/: l’attività viene visualizzata come prima.

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