Lỗi xác thực JSON
Thuộc phần API JSON trong hành trình Django của Coddy. Bài học 7 trên 19.
Hiện tại, một yêu cầu POST không có tiêu đề sẽ gây ra KeyError, và Django phản hồi bằng 500 Server Error, khiến chương trình không biết cần sửa lỗi gì.
Khi dữ liệu có vấn đề, hãy phản hồi bằng 400 Bad Request và cho biết lỗi trong JSON, mỗi trường một thông báo, giống như cách biểu mẫu Django lưu các lỗi. Ví dụ, hiệu sách kiểm tra năm xuất bản của một cuốn sách:
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)Vẫn còn hai tình huống dễ mắc lỗi. Tiêu đề chỉ gồm dấu cách không phải là chuỗi rỗng, nhưng " ".strip() là "". Phần nội dung không phải JSON sẽ khiến json.loads phát sinh json.JSONDecodeError. Hãy dùng try và except để bắt lỗi này, rồi phản hồi bằng mã 400 thay vì làm chương trình bị lỗi.
Thử thách
Trung bìnhYêu cầu POST /api/tasks/ từ chối dữ liệu không hợp lệ và trả về trạng thái 400.
- Trong
task_list, bắtjson.JSONDecodeErrorquanhjson.loadsvà phản hồi bằng{"error": "The body is not valid JSON."}. - Nếu tiêu đề bị thiếu hoặc để trống sau khi loại bỏ khoảng trắng, không lưu gì và phản hồi bằng
{"errors": {"title": "This field is required."}}. - Nếu không, hãy tạo mục đó bằng tiêu đề đã loại bỏ khoảng trắng.
Trong thẻ Shell, dòng bên dưới in ra This field is required.
from django.test import Client; print(Client().post("/api/tasks/", {"title": " "}, content_type="application/json").json())Tự làm thử
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))
Tất cả bài học trong API JSON
Tự luyện tập: Playground Django