Menu
CoddyTech

Jedna klasa na zasób

Część sekcji API JSON ścieżki Django w Coddy. Lekcja 11 z 19.

task_detail jest teraz łańcuchem bloków if request.method == ... oraz listą metod, którą trzeba z nimi uzgadniać. Klasa bazowa Django View, na której opiera się każdy użyty przez ciebie widok ogólny, zajmuje się tym śledzeniem.

Dodaj do klasy po jednej metodzie dla każdej metody HTTP, nadając im nazwy pisane małymi literami. View wywołuje metodę, której nazwa odpowiada żądaniu, a dla każdej innej zwraca odpowiedź 405. Wartości z adresu URL pojawiają się po request, tak jak w widoku funkcyjnym, a trasa używa .as_view(). Motyw kolorystyczny odwiedzającego jako zasób:

@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 działa w przypadku funkcji. W przypadku klasy method_decorator nakłada go na dispatch — metodę, przez którą przechodzi każde żądanie.

challenge icon

Wyzwanie

Średni

Przekształć task_detail w klasę TaskDetail(View):

  • Metody get, patch i delete, z których każda wykonuje to, co robiła funkcja, włącznie z odpowiedzią 404.
  • Wyłącz ochronę CSRF za pomocą method_decorator.
  • Trasa używa views.TaskDetail.as_view() i nadal ma nazwę task_detail.

Naciśnij Run, a następnie otwórz /api/tasks/1/: zadanie wyświetla się tak jak wcześniej.

Spróbuj swoich sił

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 iconSprawdź się

Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.

Wszystkie lekcje w sekcji API JSON

Poćwicz samodzielnie: Edytor online Django