Proje: Tamamlanan Görevleri Temizleme
Coddy'nin Django Journey'sinin JSON API'leri bölümünün bir parçası. Ders 16 / 19.
Tamamlanan görevler birikir, bu yüzden takip uygulamasının hepsini tek seferde temizlemenin bir yoluna ihtiyacı var. Bu işlem tek bir görevin kaynağına ait değildir, dolayısıyla kendine ait bir URL'si olur ve verileri değiştirdiği için yalnızca POST kabul eder: tarayıcılar, bağlantı önizlemeleri ve arama motorları kimseye sormadan GET istekleri gönderir; bu nedenle bir GET isteği asla silme işlemi yapmamalıdır.
Yeni olan bir ayrıntı var. Bir QuerySet'in delete() yöntemi bir çift döndürür: silinen satırların sayısı ve model başına sayımları içeren bir sözlük:
>>> Book.objects.filter(year__lt=1900).delete()
(2, {'books.Book': 2})Geri kalanını daha önce yaptın: bir görünüm, onun rotası, iki dekoratör ve bir JSON yanıtı.
Görev
ZorPOST /api/tasks/clear-done/ ekleyin; rotanın adı clear_done olsun:
- Tamamlanmış tüm görevleri siler ve silinen görev sayısını belirten
{"deleted": 1}yanıtını verir. - Diğer tüm yöntemlerde 405 yanıtını verir.
- CSRF belirteci olmadan çalışır.
Run düğmesine basın, ardından Shell sekmesinde: from django.test import Client; print(Client().post("/api/tasks/clear-done/").json())
Kendin dene
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."
priority = data.get("priority", "normal")
if priority not in Task.Priority.values:
errors["priority"] = "Choose low, normal or high."
if errors:
return JsonResponse({"errors": errors}, status=400)
task = Task.objects.create(
title=title,
priority=priority,
)
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)
priority = request.GET.get("priority")
if priority:
tasks = tasks.filter(priority=priority)
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)
JSON API'leri bölümündeki tüm dersler
Kendi başına pratik yap: Django playground