Menu
CoddyTech

Creating with POST

Part of the JSON APIs section of Coddy's Django journey. Lesson 5 of 19.

Programs can read your tasks but not add one. To create, a program sends a POST to the list's URL with the task as JSON in the request's body, the data that travels with it. A form fills request.POST; JSON does not. Read the raw body, request.body, and turn it into Python with json.loads.

One URL can do two jobs, picked by request.method. This view only echoes what it was sent:

def echo(request):
    if request.method == "POST":
        data = json.loads(request.body)
        return JsonResponse({"you_sent": data})
    return JsonResponse({"hint": "Send me a POST"})

A view that creates something answers 201 Created with the new object, so the program learns its id. A key the program may leave out is read with a default: data.get("colour", "black").

challenge icon

Challenge

Medium

Let programs create tasks with POST /api/tasks/:

  • Read the JSON body, like {"title": "Pay rent", "priority": "high"}, and create the task. Without priority it gets "normal".
  • Answer with the new task and status 201.
  • GET keeps listing and filtering.

The address bar only sends GET. Press Run, then type this in the Shell tab: from django.test import Client; print(Client().post("/api/tasks/", {"title": "Pay rent"}, content_type="application/json").json())

Try it yourself

from django.http import JsonResponse
from django.shortcuts import render

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)


def task_list(request):
    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))
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in JSON APIs

Practice on your own: Django playground