Menu
CoddyTech

Mengubah dengan PATCH

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

Program menandai tugas sebagai selesai dengan mengirim {"done": true} ke URL tugas, dan tidak mengirim apa pun lagi. URL itu merujuk pada satu tugas, yang disebut resource. Metode menentukan tindakan yang dilakukan: GET membaca resource, PATCH mengubah sebagian isinya.

Jadi, view PATCH hanya mengubah field yang ada di body. Perhatikan nilai default. Dalam API toko buku:

book.title = data.get("title", "")

Program yang hanya mengirim {"available": false} akan menghapus judul buku. Periksa terlebih dahulu apakah kuncinya dikirim: "title" in data hanya bernilai True jika kunci itu dikirim. Atur setiap field yang ada, simpan satu kali, lalu kirim respons berisi object yang telah diubah. View ini memerlukan @csrf_exempt dan metode baru di require_http_methods, seperti pada task_list.

challenge icon

Tantangan

Sedang

Biarkan program mengubah tugas.

  1. Di tasks/views.py, ganti @require_GET pada task_detail dengan dekorator yang mengizinkan GET dan PATCH, lalu tambahkan @csrf_exempt di atasnya.
  2. Untuk PATCH, baca isi JSON, tetapkan title dan done hanya jika keduanya ada di dalamnya, simpan, lalu kembalikan tugas tersebut.

Jalankan baris di bawah ini di tab Shell: baris ini mencetak tugas dengan 'done': True.

from django.test import Client; print(Client().patch("/api/tasks/1/", {"done": True}, 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 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)


@require_GET
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