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:

import json


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 responds with 201 Created and the new object, so the program learns its id.

The address bar only sends GET, so you try a POST from the Shell tab. Django's test Client sends a request to your site from Python, and .json() reads the response. The Shell prints it as a Python dictionary: 'done': False, not JSON's false.

challenge icon

Challenge

Medium

Let programs create a task.

  1. In tasks/views.py, add import json. At the top of task_list, for a POST, create the task from the JSON body's title and priority (default normal).
  2. Respond with the new task from task_to_dict and status 201. Keep the GET code below.

Run the line below in the Shell tab: it prints Pay rent with priority normal.

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