Menu
CoddyTech

Error Validasi JSON

Termasuk bagian API JSON dalam perjalanan Django di Coddy. Pelajaran 7 dari 19.

Saat ini, POST tanpa judul akan menyebabkan KeyError, dan Django merespons dengan 500 Server Error, yang tidak memberi tahu program apa yang perlu diperbaiki.

Jika datanya bermasalah, respons dengan 400 Bad Request dan jelaskan kesalahannya dalam JSON, satu pesan untuk setiap field, seperti cara formulir Django menyimpan error-nya. Toko buku memeriksa tahun sebuah buku:

errors = {}
year = data.get("year")
if not isinstance(year, int) or year < 0:
    errors["year"] = "Enter the year as a whole number."
if errors:
    return JsonResponse({"errors": errors}, status=400)

Masih ada dua jebakan. Judul yang hanya berisi spasi tidak kosong, tetapi " ".strip() adalah "". Body yang bukan JSON membuat json.loads memunculkan json.JSONDecodeError. Tangani dengan try dan except, lalu berikan respons 400 alih-alih mengalami crash.

challenge icon

Tantangan

Sedang

Buat POST /api/tasks/ menolak data yang tidak valid dengan status 400.

  1. Di task_list, tangani json.JSONDecodeError di sekitar json.loads dan berikan respons {"error": "The body is not valid JSON."}.
  2. Jika judul tidak ada atau kosong setelah dihapus spasinya, jangan simpan apa pun dan berikan respons {"errors": {"title": "This field is required."}}.
  3. Jika tidak, buat tugas dengan judul yang sudah dihapus spasinya.

Di tab Shell, baris di bawah mencetak This field is required.

from django.test import Client; print(Client().post("/api/tasks/", {"title": "  "}, content_type="application/json").json())

Coba sendiri

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":
        data = json.loads(request.body)
        task = Task.objects.create(
            title=data["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))

Semua pelajaran di API JSON

Latihan sendiri: Playground Django