أخطاء التحقق من JSON
جزء من قسم واجهات API بصيغة JSON في رحلة Django على Coddy. الدرس 7 من 19.
في الوقت الحالي، يؤدي طلب POST من دون عنوان إلى حدوث KeyError، ويرد Django بالاستجابة 500 Server Error، التي لا تخبر البرنامج بما ينبغي إصلاحه.
عندما تكون البيانات هي المشكلة، أرسل استجابة 400 Bad Request واذكر الخطأ بصيغة JSON، برسالة واحدة لكل حقل، كما يحتفظ نموذج Django بأخطائه. مثال لمتجر كتب يتحقق من سنة الكتاب:
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)ما زال هناك فخّان. العنوان الذي يتكون من مسافات فقط ليس فارغًا، لكن " ".strip() هي "". أما المتن الذي ليس بصيغة JSON فيؤدي إلى أن ترفع json.loads الاستثناء json.JSONDecodeError. عالج ذلك باستخدام try وexcept، وأرسل استجابة 400 بدلًا من حدوث عطل.
التحدي
متوسطاجعل POST /api/tasks/ يرفض البيانات غير الصالحة برمز الحالة 400.
- في
task_list، التقطjson.JSONDecodeErrorحولjson.loadsوأعِد الاستجابة{"error": "The body is not valid JSON."}. - إذا كان العنوان مفقودًا أو فارغًا بعد إزالة المسافات، فلا تحفظ شيئًا وأعِد الاستجابة
{"errors": {"title": "This field is required."}}. - وإلا، فأنشئه باستخدام العنوان بعد إزالة المسافات.
في علامة تبويب Shell، يطبع السطر أدناه This field is required.
from django.test import Client; print(Client().post("/api/tasks/", {"title": " "}, content_type="application/json").json())جرّب بنفسك
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))
جميع دروس واجهات API بصيغة JSON
2قراءة الطلبات
التصفية باستخدام استعلامالإنشاء باستخدام POSTتدرّب بنفسك: Playground لـ Django