Una clase por recurso
Parte de la sección API JSON del Journey de Django de Coddy. Lección 11 de 19.
task_detail ahora es una cadena de bloques if request.method == ... junto con una lista de métodos que hay que mantener sincronizada con ellos. La clase base de Django View, en la que se basan todas las vistas genéricas que usaste, se encarga de ese seguimiento.
Asigna a la clase un método por cada método HTTP, con el nombre en minúsculas. View llama al que lleva el nombre de la solicitud y responde con 405 para cualquier otro. Los valores de la URL llegan después de request, como en una vista de función, y la ruta usa .as_view(). El tema de color de un visitante como recurso:
@method_decorator(csrf_exempt, name="dispatch")
class Theme(View):
def get(self, request):
return JsonResponse({"theme": request.session.get("theme", "light")})
def put(self, request):
data = json.loads(request.body)
request.session["theme"] = data["theme"]
return JsonResponse({"theme": data["theme"]})@csrf_exempt funciona con funciones. En una clase, method_decorator lo aplica a dispatch, el método por el que pasa cada solicitud.
Desafío
IntermedioConvierte task_detail en una clase TaskDetail(View):
- Métodos
get,patchydelete, cada uno haciendo lo que hacía la función, incluido el 404. - Exímela de CSRF con
method_decorator. - La ruta usa
views.TaskDetail.as_view()y sigue llamándosetask_detail.
Pulsa Run y después abre /api/tasks/1/: la tarea se muestra como antes.
Pruébalo tú mismo
import json
from django.http import HttpResponse, JsonResponse
from django.shortcuts import render
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", {"tasks": Task.objects.all()})
@require_GET
def stats(request):
data = {
"total": Task.objects.count(),
"done": Task.objects.filter(done=True).count(),
}
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."
if errors:
return JsonResponse({"errors": errors}, status=400)
task = Task.objects.create(
title=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)
@csrf_exempt
@require_http_methods(["GET", "PATCH", "DELETE"])
def task_detail(request, pk):
task = Task.objects.filter(pk=pk).first()
if task is None:
return JsonResponse({"error": "Task not found"}, status=404)
if request.method == "DELETE":
task.delete()
return HttpResponse(status=204)
if request.method == "PATCH":
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))
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de API JSON
2Lectura de solicitudes
Filtrar con una consultaCrear con POST5Proyecto: Organizar el trabajo
Proyecto: PrioridadesProyecto: Borrar las tareas completadasPractica por tu cuenta: Playground de Django