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
MediumLet programs create a task.
- In
tasks/views.py, addimport json. At the top oftask_list, for aPOST, create the task from the JSON body'stitleandpriority(defaultnormal). - Respond with the new task from
task_to_dictand status201. 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))
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in JSON APIs
2Reading Requests
Filter with a QueryCreating with POSTPractice on your own: Django playground