Проект: Очистка выполненных задач
Часть раздела JSON API путешествия по Django на Coddy. Урок 16 из 19.
Выполненные задачи накапливаются, поэтому трекеру нужен способ очистить их все сразу. Очистка применяется сразу ко многим задачам, а не к одной, поэтому для неё используется отдельный URL. А поскольку она изменяет данные, она принимает только POST: браузеры, предварительный просмотр ссылок и поисковые системы отправляют GET-запросы, не спрашивая разрешения, поэтому GET-запрос ни в коем случае не должен удалять данные.
Есть одна новая деталь. Метод delete() у QuerySet возвращает пару: количество удалённых строк и словарь с количеством удалённых строк для каждой модели:
>>> Book.objects.filter(year__lt=1900).delete()
(2, {'books.Book': 2})Остальное вы уже делали: представление, его маршрут, два декоратора и ответ в формате JSON.
Задание
СложноДобавь конечную точку, которая удаляет все выполненные задачи.
- В
tasks/views.pyдобавь представлениеclear_done. Оно удаляет все выполненные задачи и возвращает{"deleted": 1}— количество удалённых задач. При любом методе, кромеPOST, возвращается405; токен CSRF не требуется. - В
tasks/urls.pyдобавь маршрут"api/tasks/clear-done/"с именемclear_done.
Выполни приведённую ниже строку на вкладке Shell: она выводит {'deleted': 1}, поскольку Call the bank была единственной выполненной задачей.
from django.test import Client; print(Client().post("/api/tasks/clear-done/").json())Попробуйте сами
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
Потренируйтесь самостоятельно: Песочница Django