Menu
CoddyTech

Proyek: Prioritas

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

Saatnya menambahkan fitur sendiri. Setiap tugas memiliki priority: low, normal, atau high. API harus memungkinkan program meminta satu prioritas dan mencegah siapa pun membuat prioritas keempat.

Kamu sudah memiliki semua yang dibutuhkan: request.GET.get() untuk filter, QuerySet yang bisa kamu filter lebih dari sekali, dan dictionary errors yang memberikan respons 400.

Nilai yang diizinkan ada di model. Task.Priority adalah class TextChoices, dan Task.Priority.values adalah list ["low", "normal", "high"]. Dengan memeriksa nilai terhadapnya, prioritas yang ditambahkan ke model nanti akan diterima tanpa perlu mengubah view.

challenge icon

Tantangan

Sedang

Tambahkan prioritas ke API:

  • /api/tasks/?priority=high hanya menampilkan task dengan prioritas tinggi, dan berfungsi bersama ?done=: ?priority=high&done=false.
  • POST dengan prioritas selain low, normal, atau high memberikan respons 400 dengan error di bawah "priority", dan tidak menyimpan apa pun.
  • Jika tidak ada prioritas, nilai defaultnya tetap normal.

Tekan Jalankan: pratinjau menampilkan satu task dengan prioritas tinggi.

Coba sendiri

import json

from django.http import HttpResponse, JsonResponse
from django.shortcuts import get_object_or_404, render
from django.utils.decorators import method_decorator
from django.views import View
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")


def task_page(request):
    return render(request, "tasks/list.html", {"tasks": Task.objects.all()})


def task_row(request, pk):
    task = get_object_or_404(Task, pk=pk)
    return render(request, "tasks/list.html#task-row", {"task": task})


@require_GET
def stats(request):
    total = Task.objects.count()
    done = Task.objects.filter(done=True).count()
    data = {
        "total": total,
        "done": done,
        "open": total - done,
    }
    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)


def not_found():
    return JsonResponse({"error": "Task not found"}, status=404)


@method_decorator(csrf_exempt, name="dispatch")
class TaskDetail(View):
    def get(self, request, pk):
        task = Task.objects.filter(pk=pk).first()
        if task is None:
            return not_found()
        return JsonResponse(task_to_dict(task))

    def patch(self, request, pk):
        task = Task.objects.filter(pk=pk).first()
        if task is None:
            return not_found()
        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))

    def delete(self, request, pk):
        task = Task.objects.filter(pk=pk).first()
        if task is None:
            return not_found()
        task.delete()
        return HttpResponse(status=204)

Semua pelajaran di API JSON

Latihan sendiri: Playground Django