허용된 메서드
Coddy Django 여정의 JSON API 섹션에 포함된 레슨. 19개 중 8번째.
DELETE /api/tasks/를 보내면 작업을 나열하는 코드로 넘어가 200을 반환합니다. 마치 요청이 처리된 것처럼 보입니다. 무언가를 삭제해 달라고 요청한 프로그램은 이제 삭제가 완료되었다고 생각합니다.
올바른 응답은 405 Method Not Allowed입니다. django.views.decorators.http의 데코레이터는 뷰가 실행되기 전에 이 응답을 반환하며, 뷰가 허용하는 메서드를 나열하는 Allow 헤더도 함께 보냅니다.
@require_POST
def subscribe(request):
...
@require_http_methods(["GET", "PUT"])
def profile(request):
...require_GET과 require_POST는 각각 하나의 메서드만 지정하는 축약형입니다. 뷰에는 한 줄에 하나씩 데코레이터 두 개를 붙일 수 있습니다. 예를 들어 @require_POST 위에 @csrf_exempt를 붙이는 방식입니다. 뷰의 코드가 실제로 처리하는 메서드만 정확히 허용하세요.
챌린지
쉬움뷰가 처리하지 않는 메서드에는 405를 응답합니다:
task_list는GET및POST를 허용합니다.stats와task_detail은GET만 허용합니다.
Run을 누른 다음 Shell 탭에서: from django.test import Client; print(Client().delete("/api/stats/").status_code)를 실행하면 405가 출력됩니다.
직접 해보기
import json
from django.http import JsonResponse
from django.shortcuts import render
from django.views.decorators.csrf import csrf_exempt
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()})
def stats(request):
data = {
"total": Task.objects.count(),
"done": Task.objects.filter(done=True).count(),
}
return JsonResponse(data)
@csrf_exempt
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)
def task_detail(request, pk):
task = Task.objects.filter(pk=pk).first()
if task is None:
return JsonResponse({"error": "Task not found"}, status=404)
return JsonResponse(task_to_dict(task))
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.
JSON API의 모든 레슨
직접 연습해 보세요: Django 플레이그라운드