5. Hello DRF

Django REST Framework has 2 of its own components for managing the database.

  1. Serializers: They convert model instances (database queries) into JSON format (serialize), or vice versa (deserialize).
  2. ViewSets: Similar to Django's Views, except that they automate the responses, the verbs (GET, POST...), the models that will be used, and how the resulting data will be serialized (Serializers).

We are going to create a model, or table in the database, to manage the books.

First we create a test to verify that they are created correctly.

# tests/libros/test_create_model.py

import pytest

from app.libros.models import Libros

@pytest.mark.django_db
def test_libros_model():

    ## Given
    # We create a new book in the database
    libro = Libros(
        title="La fundación",
        genre="Ciencia ficción",
        year="1951",
        author="Isaac Asimov",
    )
    libro.save()

    ## When

    ## Then
    assert libro.title == "La fundación"
    assert libro.genre == "Ciencia ficción"
    assert libro.year == "1951"
    assert libro.author == "Isaac Asimov"
    assert libro.created_at
    assert libro.updated_at
    assert str(libro) == libro.title

We run it.

pytest

Of course, it will tell us it does not pass. The model does not exist. Let's define it.

# app/libros/models.py

from django.contrib.auth.models import AbstractUser
from django.db import models

class Libros(models.Model):
    title = models.CharField(max_length=255)
    genre = models.CharField(max_length=255)
    year = models.CharField(max_length=4)
    author = models.CharField(max_length=255)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        ordering = ("-created_at",)
        verbose_name = "Libro"
        verbose_name_plural = "Libros"

    def __str__(self):
        return self.title

I do not recommend using uuid or a bigint as the Id in a model or as the primary key in a database. When the data in a database grows, its weight increases considerably, reaching up to 20% of its capacity in keys. You can read more about it in a fantastic article by Shekhar Gulati.

We prepare the migration.

python3 manage.py makemigrations

We run it again.

python3 manage.py migrate

And we try the test.

pytest

It will pass without any problems.

Now we are going to define the serializer to transform the database results (models) into JSON. As always, we start with the test.

# tests/libros/test_serializers.py

from app.libros.serializers import LibroSerializer

def test_valid_libro_serializer():
    valid_serializer_data = {
        "title": "Raising Arizona",
        "genre": "comedy",
        "year": "1987",
        "author": "Ray Bradbury",
    }
    serializer = LibroSerializer(data=valid_serializer_data)
    assert serializer.is_valid()
    assert serializer.validated_data == valid_serializer_data
    assert serializer.data == valid_serializer_data
    assert serializer.errors == {}

def test_invalid_libro_serializer():
    invalid_serializer_data = {
        "title": "Soy Leyenda",
        "author": "Richard Matheson",
    }
    serializer = LibroSerializer(data=invalid_serializer_data)
    assert not serializer.is_valid()
    assert serializer.validated_data == {}
    assert serializer.data == invalid_serializer_data
    assert serializer.errors == {
        "year": ["This field is required."],
        "genre": ["This field is required."],
    }

It will fail, of course. We have not built the serializer.

pytest

Thanks to getting ahead of ourselves in the test, we already know how it should be structured.

We create the serializer.

# app/libros/serializers.py

from rest_framework import serializers
from .models import Libros

class LibroSerializer(serializers.ModelSerializer):
    class Meta:
        model = Libros
        fields = "__all__"
        read_only_fields = (
            "id",
            "created_at",
            "updated_at",
        )

We tell it to use all the fields, and that it can only read id, created_at, and updated_at.

Now we can pass the test. If you only want to check the last one we made, you can narrow it down with the -k argument and the file name, leaving out the test_. prefix.

pytest -k serializers

This work is under a Attribution-NonCommercial-NoDerivatives 4.0 International license.

Desafíos de programación atemporales y multiparadigmáticos

Desafíos de programación atemporales y multiparadigmáticos

Te encuentras ante un librillo de actividades, divididas en 2 niveles de dificultad. Te enfrentarás a los casos más comunes que te puedes encontrar en pruebas técnicas o aprender conceptos elementales de programación.

Buy the book

Will you buy me a coffee?

This is how I keep writing without ads or paywalls.

Comments

There are no comments yet.