Menu
CoddyTech

Eine Klasse pro Ressource

Teil des Abschnitts JSON-APIs der Django-Journey von Coddy. Lektion 11 von 19.

task_detail besteht jetzt aus einer Kette von if request.method == ...-Blöcken sowie einer Liste von Methoden, die damit Schritt halten muss. Djangos Basisklasse View, die jeder von dir verwendeten generischen Ansicht zugrunde liegt, übernimmt diese Verwaltungsarbeit.

Gib der Klasse für jede HTTP-Methode eine Methode mit einem Namen in Kleinbuchstaben. View ruft die Methode auf, die nach der Anfrage benannt ist, und antwortet auf alle anderen mit 405. Werte aus der URL folgen auf request, wie bei einer Funktionsansicht, und die Route verwendet .as_view(). Hier ist die Ressource das Farbdesign eines Besuchers, das in der Sitzung gespeichert wird:

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 funktioniert bei Funktionen. Bei einer Klasse setzt method_decorator es auf dispatch, die Methode, die jede Anfrage durchläuft.

challenge icon

Aufgabe

Mittel

Wandle task_detail in eine Klasse um.

  1. Importiere in tasks/views.py View aus django.views und method_decorator aus django.utils.decorators.
  2. Ersetze die Funktion und beide Decorators durch class TaskDetail(View). Die Methoden get, patch und delete nehmen (self, request, pk) entgegen und führen jeweils die Arbeit ihres bisherigen Zweigs aus.
  3. Nimm die Klasse vom CSRF-Schutz aus, indem du method_decorator(csrf_exempt) auf dispatch anwendest.
  4. Leite in tasks/urls.py an views.TaskDetail.as_view() weiter; der Name bleibt task_detail.

Öffne /api/tasks/1/: Buy milk wird als JSON angezeigt.

Probier es selbst

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 iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in JSON-APIs

Übe selbstständig: Django-Playground