Progetto: cancellare le attività completate
Fa parte della sezione API JSON del percorso Django di Coddy. Lezione 16 di 19.
Le attività completate si accumulano, quindi il tracker ha bisogno di un modo per eliminarle tutte in una volta. L'eliminazione riguarda più attività alla volta, non una sola, quindi ha un URL dedicato e, poiché modifica i dati, accetta solo POST: browser, anteprime dei link e motori di ricerca inviano richieste GET senza chiedere a nessuno, quindi una richiesta GET non deve mai eliminare nulla.
C'è un dettaglio nuovo. Il metodo delete() di un QuerySet restituisce una coppia: il numero di righe eliminate e un dizionario con il conteggio per modello:
>>> Book.objects.filter(year__lt=1900).delete()
(2, {'books.Book': 2})Il resto lo hai già realizzato: una vista, la sua route, due decoratori e una risposta JSON.
Sfida
DifficileAggiungi un endpoint che elimina tutte le attività completate.
- In
tasks/views.py, aggiungi una vistaclear_done. Elimina tutte le attività completate e risponde con{"deleted": 1}, il numero di attività eliminate. Qualsiasi metodo diverso daPOSTriceve405; l’endpoint funziona anche senza token CSRF. - In
tasks/urls.py, aggiungi la route"api/tasks/clear-done/"con il nomeclear_done.
Esegui la riga qui sotto nella scheda Shell: stampa {'deleted': 1}, perché Call the bank era l’unica attività completata.
from django.test import Client; print(Client().post("/api/tasks/clear-done/").json())Provalo tu
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)
Tutte le lezioni di API JSON
2Lettura delle richieste
Filtrare con una queryCreare con POST5Progetto: organizzare il lavoro
Progetto: le prioritàProgetto: cancellare le attività completateEsercitati da solo: Playground Django