7. Details
Now we will take care of viewing the details of a specific book (GET).
We create the tests so we can check whether it returns the data of a specific book, and another one to check that it returns an error if it does not exist. We add both tests to tests/libros/test_views.py.
# tests/libros/test_views.py
import pytest
from app.libros.models import Libros
@pytest.mark.django_db
def test_add_book(client):
# Given
libros = Libros.objects.all()
assert len(libros) == 0
# When
resp = client.post(
"/api/libros/",
{
"title": "El fin de la eternidad",
"genre": "Ciencia Ficción",
"author": "Isaac Asimov",
"year": "1955",
},
content_type="application/json"
)
# Then
assert resp.status_code == 201
assert resp.data["title"] == "El fin de la eternidad"
libros = Libros.objects.all()
assert len(libros) == 1
@pytest.mark.django_db
def test_get_single_book(client): # new
# Given
libro = Libros.objects.create(
title="El fin de la eternidad",
genre="Ciencia Ficción",
author="Isaac Asimov",
year="1955",
)
# When
resp = client.get(f"/api/libros/{libro.id}/")
# Then
assert resp.status_code == 200
assert resp.data["title"] == "El fin de la eternidad"
@pytest.mark.django_db
def test_get_single_libro_incorrect_id(client): # new
# When
resp = client.get(f"/api/libros/-1/")
# Then
assert resp.status_code == 404
It is time to define the view.
# app/libros/views.py
from django.http import JsonResponse
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from .serializers import LibroSerializer
from .models import Libros
def ping(request):
data = {"ping": "pong!"}
return JsonResponse(data)
class LibrosList(APIView):
def post(self, request):
serializer = LibroSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
class LibrosDetails(APIView): # new
def get(self, request, pk):
libro = Libros.objects.filter(pk=pk).first()
serializer = LibroSerializer(libro)
if libro:
return Response(serializer.data, status=status.HTTP_200_OK)
return Response(serializer.errors, status=status.HTTP_404_NOT_FOUND)
And register its url. We tell it that it will need a number after libros. For example api/libros/23/.
# app/libros/urls.py
from django.urls import path
from app.libros.views import *
urlpatterns = [
path("ping/", ping, name="ping"),
path("api/libros/", LibrosList.as_view()),
path("api/libros/<int:pk>/", LibrosDetails.as_view()), # new
]
The test will now pass.
You can also check with an HTTP client what you receive. (Don't forget to start the server and create a book)
# curl
curl http://localhost:8000/api/libros/1/
# HTTPie
http GET http://localhost:8000/api/libros/1/
Allow: GET, HEAD, OPTIONS
Content-Length: 192
Content-Type: application/json
Date: Mon, 12 Jul 2021 21:00:51 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.9.2
Vary: Accept, Cookie
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
{
"author": "Isaac Asimov",
"created_at": "2021-07-11T21:30:04.088124Z",
"genre": "Ciencia Ficción",
"id": 1,
"title": "El fin de la eternidad",
"updated_at": "2021-07-11T21:30:04.088160Z",
"year": "1955"
}
This work is under a Attribution-NonCommercial-NoDerivatives 4.0 International license.
Building SPAs with Django and HTML Over the Wire: Learn to build real-time single page applications with Python
The HTML over WebSockets approach simplifies single-page application (SPA) development and lets you bypass learning a JavaScript rendering framework such as React, Vue, or Angular, moving the logic to Python. This web application development book provides you with all the Django tools you need to simplify your developments with real-time results.
Buy the bookHelp me keep writing
Every coffee gives me a push toward the next article.
Sure, it's on me!
Comments
There are no comments yet.