리소스마다 하나의 클래스
Coddy Django 여정의 JSON API 섹션에 포함된 레슨. 19개 중 11번째.
task_detail은 이제 if request.method == ... 블록과 그에 맞춰 함께 관리해야 하는 메서드 목록으로 이루어져 있습니다. 사용한 모든 제네릭 뷰의 기반 클래스인 Django의 View가 이러한 관리를 대신 처리합니다.
클래스에 HTTP 메서드마다 하나씩, 소문자로 이름을 붙인 메서드를 작성하세요. View는 요청에 해당하는 이름의 메서드를 호출하고, 그 외의 메서드에는 405를 응답합니다. 함수형 뷰에서처럼 URL의 값은 request 다음에 전달되며, 경로에서는 .as_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는 함수에서 사용할 수 있습니다. 클래스에서는 method_decorator가 모든 요청이 거쳐 가는 메서드인 dispatch에 이를 적용합니다.
챌린지
중급task_detail을 클래스 TaskDetail(View)로 바꾸세요.
get,patch,delete메서드를 만들고, 각각 기존 함수와 같은 작업을 수행하게 하세요. 404 처리도 포함합니다.method_decorator를 사용해 CSRF 검사를 면제하세요.- 라우트는
views.TaskDetail.as_view()를 사용하며, 이름은 계속task_detail로 지정합니다.
실행을 누른 다음 /api/tasks/1/을 여세요. 작업이 이전과 같이 표시됩니다.
직접 해보기
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))
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.
JSON API의 모든 레슨
직접 연습해 보세요: Django 플레이그라운드