Dự án: Mức độ ưu tiên
Thuộc phần API JSON trong hành trình Django của Coddy. Bài học 15 trên 19.
Đến lúc tự thêm một tính năng. Mỗi nhiệm vụ có một priority: low, normal hoặc high. API nên cho phép chương trình yêu cầu một mức độ ưu tiên và ngăn mọi người tự thêm mức thứ tư.
Bạn đã có đủ mọi thứ: request.GET.get() để lọc, một QuerySet mà bạn có thể lọc nhiều lần, và từ điển errors mà bạn gửi lại cùng mã 400.
Các giá trị được phép nằm trong model. Task.Priority là một lớp TextChoices, còn Task.Priority.values là danh sách ["low", "normal", "high"]. Kiểm tra giá trị trong danh sách này có nghĩa là sau này, nếu bạn thêm một mức độ ưu tiên vào model, hệ thống vẫn chấp nhận mức đó mà bạn không cần sửa view.
Thử thách
Trung bìnhTrong task_list ở tasks/views.py, hãy thêm mức độ ưu tiên. ?priority=high chỉ liệt kê các nhiệm vụ có mức độ ưu tiên cao và cũng dùng được cùng với ?done=: ?priority=high&done=false. Nếu một yêu cầu POST có mức độ ưu tiên khác low, normal hoặc high, hệ thống sẽ không lưu gì và phản hồi 400 cùng thông báo bên trong từ điển errors, chẳng hạn {"errors": {"priority": "Choose low, normal or high."}}. Nếu không có mức độ ưu tiên, giá trị mặc định vẫn là normal.
Nhấn Chạy: bản xem trước mở /api/tasks/?priority=high và liệt kê Write the report.
Tự làm thử
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)
Tất cả bài học trong API JSON
Tự luyện tập: Playground Django