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.
Aufgabe
MittelWandle task_detail in eine Klasse um.
- Importiere in
tasks/views.pyViewausdjango.viewsundmethod_decoratorausdjango.utils.decorators. - Ersetze die Funktion und beide Decorators durch
class TaskDetail(View). Die Methodenget,patchunddeletenehmen(self, request, pk)entgegen und führen jeweils die Arbeit ihres bisherigen Zweigs aus. - Nimm die Klasse vom CSRF-Schutz aus, indem du
method_decorator(csrf_exempt)aufdispatchanwendest. - Leite in
tasks/urls.pyanviews.TaskDetail.as_view()weiter; der Name bleibttask_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))
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