Lección 5: Hola DRF

Django REST Framework dispone de 2 componentes propios para la gestión de la base de datos.

  1. Serializadores: Convierten instancias de modelos (consultas a la base de datos) en formato JSON (serializar), o viceversa (deserializar).
  2. ViewSets: Similares a las Views (Vistas) de Django, salvo que automatizan las respuestas, verbos (GET, POST…), los modelos que se utilizarán y como se serializará la información resultante (Serializadores).

Vamos a crear un modelo, o tabla en la base de datos, para gestionar los libros.

Primero creamos un test para verificar que se crean correctamente.

# tests/libros/test_create_model.py

import pytest

from app.libros.models import Libros

@pytest.mark.django_db
def test_libros_model():

    ## Given
    # Creamos un nuevo libro en la base de datos
    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

Lo ejecutamos.

pytest

Por supuesto, nos dirá que no pasa. El modelo no existe. Vamos a definirlo.

# 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

No recomiendo utilizar uuid o un bigint como Id en un modelo o como clave primaria en una base de datos. Cuando la información en una base de datos crece aumenta considerablemente su peso, llegado hasta ocupar hasta un 20% de su capacidad en claves. Podéis leer más al respecto en un fantástico artículo de Shekhar Gulati.

Preparamos la migración.

python3 manage.py makemigrations

La ejecutamos de nuevo.

python3 manage.py migrate

Y probamos el test.

pytest

Pasará sin problemas.

Ahora vamos a definir el serializador para transformar los resultados de la base de datos (models) a JSON. Como siempre, empezamos por el 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."],
    }

Nos fallará, por supuesto. No hemos realizado el serializador.

pytest

Gracias a adelantarnos en el test ya sabemos como debe estar estructurado.

Creamos el serializador.

# 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",
        )

Le indicamos que use todos los campos, y que solo pueda leer id, created_at y updated_at.

Ahora ya podemos pasar el test. Si solo deseas comprobar el último que hemos realizado, puedes concretar con el argumento -k y el nombre del archivo evitando el prefijo test_.

pytest -k serializers

Esta obra está bajo una Licencia Creative Commons Atribución-NoComercial-SinDerivadas 4.0 Internacional.

Atribución/Reconocimiento-NoComercial-SinDerivados 4.0 Internacional

¿Me invitas a un café? ☕

Puedes hacerlo usando el terminal.

ssh customer@andros.dev -p 5555

Comentarios

{{ comments.length }} comentarios

Nuevo comentario

Nueva replica  {{ formatEllipsisAuthor(replyComment.author) }}

Acepto la política de Protección de Datos.

Escribe el primer comentario