API navegable en Django REST Framework

La función de API navegable en el marco Django REST genera una salida HTML para diferentes recursos. Facilita la interacción con el servicio web RESTful a través de cualquier navegador web. Para habilitar esta función, debemos especificar texto/html para la clave de tipo de contenido en el encabezado de la solicitud. Nos ayuda a utilizar navegadores web para navegar a través de la API y puede realizar diferentes requests HTTP. En esta sección, trabajaremos con la función de API navegable en el marco de la API REST de Django.  

¿Cómo crear una API básica usando Django Rest Framework?

Cree un proyecto simple para demostrar las API navegables: 

Vamos a crear modelos, serializadores y vistas necesarios para nuestros robots de aplicaciones.

Creación de modelos

En Django, los modelos son clases que tratan con bases de datos de forma orientada a objetos. Cada clase de modelo hace referencia a una tabla de base de datos y cada atributo de la clase de modelo hace referencia a una columna de base de datos. Aquí, crearemos los siguientes modelos:

  • RobotCategory (Categorías de robots)
  • Fabricante (Detalles del fabricante)
  • Robot (Detalles del robot)

El modelo RobotCategory requiere:

  • Nombre de categoría de robot

El modelo de Fabricante requiere:

  • Nombre del Fabricante

El modelo de Robot requiere:

  • Nombre del robot
  • Una clave externa al modelo RobotCategory
  • Una clave externa al modelo Manufacturer
  • Divisa
  • Precio
  • Fecha de fabricación

Analicemos el verbo HTTP, la semántica de alcance en nuestro servicio web robots Restful.

Verbo HTTP Alcance Semántica URL
OBTENER Categoría de robots Recuperar una categoría de robot http://localhost:8000/robocategory/{id}/
OBTENER Colección de la categoría Robot Recupera todas las categorías de robots de la colección. http://localhost:8000/robocategoría/
CORREO Colección de la categoría Robot Crear una nueva categoría de robot en la colección http://localhost:8000/robocategory/{id}/
PONER Categoría de robots Actualizar una categoría de robot http://localhost:8000/robocategory/{id}/
ELIMINAR Categoría de robots Eliminar una categoría de robot http://localhost:8000/robocategory/{id}/
OBTENER Fabricante Recuperar un fabricante  http://localhost:8000/fabricante/{id}/
OBTENER Colección de fabricante Recuperar todos los fabricantes de la colección. http://localhost:8000/fabricante/
CORREO Colección de fabricante Crear un fabricante en la colección http://localhost:8000/fabricante/{id}/
PONER Fabricante Actualizar un fabricante http://localhost:8000/fabricante/{id}/
ELIMINAR Fabricante Eliminar un fabricante http://localhost:8000/fabricante/{id}/
OBTENER Robot recuperar un robot http://localhost:8000/robot/{id}/
OBTENER colección de robots Recupera todos los robots de la colección. http://localhost:8000/robot/
CORREO colección de robots Crear un robot en la colección. http://localhost:8000/robot/{id}/
PONER Robot Actualizar un robot http://localhost:8000/robot/{id}/
ELIMINAR Robot Eliminar un robot http://localhost:8000/robot/{id}/

Vamos a crear los modelos para la categoría de robot, el fabricante, el robot y sus relaciones. Puede agregar el siguiente código en el archivo models.py.

Python3

from django.db import models
  
class RobotCategory(models.Model):
    name = models.CharField(max_length=150, unique=True)
  
    class Meta:
        ordering = ('name',)
  
    def __str__(self):
        return self.name
  
class Manufacturer(models.Model):
    name = models.CharField(max_length=150, unique=True)
  
    class Meta:
        ordering = ('name',)
  
    def __str__(self):
        return self.name
  
class Robot(models.Model):
    CURRENCY_CHOICES = (
        ('INR', 'Indian Rupee'),
        ('USD', 'US Dollar'),
        ('EUR', 'Euro'),
    )
  
    name = models.CharField(max_length=150, unique=True)
    robot_category = models.ForeignKey(
        RobotCategory,
        related_name='robots',
        on_delete=models.CASCADE)
    manufacturer = models.ForeignKey(
        Manufacturer,
        related_name='robots',
        on_delete=models.CASCADE)
    currency = models.CharField(
        max_length=3,
        choices= CURRENCY_CHOICES,
        default='INR')
    price = models.IntegerField()
    manufacturing_date = models.DateTimeField()
  
    class Meta:
        ordering = ('name',)
  
    def __str__(self):
        return self.name

Aquí tenemos tres clases que son subclases de la clase django.db.models.Model:

  • RobotCategoría
  • Fabricante
  • Robot

La clase Robot tiene una relación de muchos a uno con el modelo RobotCategory y el modelo Manufacturer. Esta relación se logra haciendo uso de la clase django.db.models.ForeignKey. El código de la siguiente manera:

    robot_category = models.ForeignKey(
        RobotCategory,
        related_name='robots',
        on_delete=models.CASCADE)
    manufacturer = models.ForeignKey(
        Manufacturer,
        related_name='robots',
        on_delete=models.CASCADE)

El argumento related_name crea una relación inversa. Aquí, el valor ‘robots’ en related_name crea una relación inversa de RobotCategory a Robot y Manufacturer a Robot. Esto facilita la búsqueda de todos los robots que pertenecen a una categoría de robots y también en función del fabricante.

A continuación, puede realizar el proceso de migración y aplicar toda la migración generada. Puedes usar los siguientes comandos

python manage.py hacer migraciones

python manage.py migrar

Creación de serializadores

Ahora, necesitamos serializar las instancias de RobotCategory, Manufacturer y Robot. Aquí, usaremos HyperlinkedModelSerializer para manejar las relaciones del modelo. Puede consultar el tema Relaciones del serializador DRF para comprenderlo en detalle.

Python3

from rest_framework import serializers
from robots.models import RobotCategory, Manufacturer, Robot
  
class RobotCategorySerializer(serializers.HyperlinkedModelSerializer):
    robots = serializers.HyperlinkedRelatedField(
        many=True,
        read_only=True,
        view_name='robot-detail')
  
    class Meta:
        model = RobotCategory
        fields = '__all__'
  
  
class ManufacturerSerializer(serializers.HyperlinkedModelSerializer):
    robots = serializers.HyperlinkedRelatedField(
        many=True,
        read_only=True,
        view_name='robot-detail')
  
    class Meta:
        model = Manufacturer
        fields = '__all__'
  
class RobotSerializer(serializers.HyperlinkedModelSerializer):
    robot_category = serializers.SlugRelatedField(
        queryset=RobotCategory.objects.all(), slug_field='name')
    manufacturer = serializers.SlugRelatedField(
        queryset=Manufacturer.objects.all(), slug_field='name')
    currency = serializers.ChoiceField(
        choices=Robot.CURRENCY_CHOICES)
    currency_name = serializers.CharField(
        source='get_currency_display',
        read_only=True)
  
    class Meta:
        model = Robot
        fields = '__all__'

Las clases RobotCategorySerializer y ManufacturerSerializer son subclases de la clase HyperlinkedModelSerializer, y la relación inversa (RobotCategory a Robot y Manufacturer a Robot) se representa mediante HyperlinkedRelatedField con muchos y atributos de solo lectura establecidos en True. view_name (robot-detail) permite que la función de API navegable proporcione una función de clic para que el usuario represente el hipervínculo. 

La clase RobotSerializer también es una subclase de la clase HyperlinkedModelSerializer. La clase RobotSerializer declara dos atributos, robot_category y manufacturer, que contiene una instancia de serializers.SlugRelatedField. Un campo relacionado con Slug representa una relación mediante un atributo de slug único.

Creación de vistas

Hagamos uso de vistas genéricas basadas en clases proporcionadas por Django REST Framework para procesar las requests HTTP y proporcionar las respuestas HTTP adecuadas. Puede consultar las vistas basadas en la clase DRF para obtener una explicación detallada.

Python3

from django.shortcuts import render
  
from rest_framework import generics
from rest_framework.response import Response
from rest_framework.reverse import reverse
  
from robots.models import RobotCategory, Manufacturer, Robot
from robots.serializers import RobotCategorySerializer, \
     ManufacturerSerializer, RobotSerializer
  
  
class ApiRoot(generics.GenericAPIView):
    name = 'api-root'
    def get(self, request, *args, **kwargs):
        return Response({
            'robot-categories': reverse(RobotCategoryList.name, request=request),
            'manufacturers': reverse(ManufacturerList.name, request=request),
            'robots': reverse(RobotList.name, request=request)
            })    
  
  
class RobotCategoryList(generics.ListCreateAPIView):
    queryset = RobotCategory.objects.all()
    serializer_class = RobotCategorySerializer
    name = 'robotcategory-list'
  
class RobotCategoryDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = RobotCategory.objects.all()
    serializer_class = RobotCategorySerializer
    name = 'robotcategory-detail'
  
class ManufacturerList(generics.ListCreateAPIView):
    queryset = Manufacturer.objects.all()
    serializer_class = ManufacturerSerializer
    name= 'manufacturer-list'
  
class ManufacturerDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Manufacturer.objects.all()
    serializer_class = ManufacturerSerializer
    name = 'manufacturer-detail'
  
class RobotList(generics.ListCreateAPIView):
    queryset = Robot.objects.all()
    serializer_class = RobotSerializer
    name = 'robot-list'
  
class RobotDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Robot.objects.all()
    serializer_class = RobotSerializer
    name = 'robot-detail'

Aquí, nuestras clases de vista se importan desde rest_framework.generics y aprovechamos dos vistas genéricas basadas en clases: ListCreateAPIView y RetrieveUpdateDestroyAPIView.

Puede notar que una clase ApiRoot, una subclase de generics.GenericAPIView, crea un punto final para la raíz de nuestro servicio web. Facilita la exploración de los recursos con la función de API explorable. 

class ApiRoot(generics.GenericAPIView):
    name = 'api-root'
    def get(self, request, *args, **kwargs):
        return Response({
            'robot-categories': reverse(RobotCategoryList.name, request=request),
            'manufacturers': reverse(ManufacturerList.name, request=request),
            'robots': reverse(RobotList.name, request=request)
            })    

El método get devuelve un objeto Response (como un par de strings clave/valor) que tiene el nombre descriptivo de la vista y su URL.

Configuración de configuración de URL

Vaya a la carpeta de aplicaciones (robots) y cree un nuevo archivo llamado archivo urls.py. Puede agregar el siguiente código:

Python3

from django.urls import path
from robots import views
  
urlpatterns = [
    path('robocategory/',
         views.RobotCategoryList.as_view(),
         name='robotcategory-list'),
    path('robocategory/<int:pk>/',
         views.RobotCategoryDetail.as_view(),
         name='robotcategory-detail'),
    path('manufacturer/',
         views.ManufacturerList.as_view(),
         name='manufacturer-list'),
    path('manufacturer/<int:pk>/',
         views.ManufacturerDetail.as_view(),
         name='manufacturer-detail'),
    path('robot/',
         views.RobotList.as_view(),
         name='robot-list'),
    path('robot/<int:pk>/',
         views.RobotDetail.as_view(),
         name='robot-detail'),
    path('',
        views.ApiRoot.as_view(),
        name=views.ApiRoot.name)
]

Define el patrón de URL que debe coincidir en la solicitud para ejecutar el método particular para una vista basada en clases definida en el archivo views.py. Ahora tenemos que establecer la configuración de la URL raíz. Puede agregar el siguiente código:

Python3

from django.contrib import admin
from django.urls import path, include
  
urlpatterns = [
    path('', include('robots.urls')),
]

¿Cómo realizar requests a la API utilizando la API navegable?

Redactemos y enviemos requests HTTP para generar contenido de texto/html en la respuesta. El servicio web RESTFul utiliza la clase BrowsableAPIRenderer para generar contenido HTML. El comando HTTPie para aceptar texto/html de la siguiente manera:

http -v :8000/robot/ “Aceptar:texto/html”

Compartiendo la captura de pantalla del símbolo del sistema para su referencia

Antes de utilizar la API navegable, creemos una nueva entrada para Categoría de robot, Fabricante y Robot mediante el comando HTTPie. El comando de la siguiente manera:

http POST :8000/robocategory/ name=”Robots Articulados”

http POST :8000/fabricante/nombre=”Fanuc”

http POST :8000/robot/ name=”FANUC M-710ic/50″ robot_category=”Robots articulados” fabricante=”Fanuc” moneda=”USD” precio=37000 manufacturing_date=”2019-10-12 00:00:00+ 00:00″

OBTENER solicitud HTTP

Ahora, exploremos el servicio web Restful de ‘robots’ usando un navegador. Puede utilizar la siguiente URL.

http://localhost:8000/

Compartiendo la captura de pantalla del navegador para su referencia

Puede hacer clic en el enlace que corresponde a las categorías de robots, fabricantes y robots y verificar los datos. Compartir la captura de pantalla del navegador que muestra el resultado de robots (http://localhost:8000/robot/)

POST Solicitud HTTP

A continuación, creemos una nueva categoría de robot. Puede navegar por el siguiente enlace y desplazarse hacia abajo.

http://localhost:8000/robocategoría/

Compartiendo la captura de pantalla del navegador para su referencia

Puede escribir el nombre de la nueva categoría de robot y hacer clic en el botón POST. Aquí, se muestra en formato HTML. Si elige Datos sin procesar, seleccione el tipo de medio como aplicación/json, complete el nuevo nombre de categoría de robot en el campo de nombre y haga clic en el botón POST. Compartiendo la captura de pantalla para su referencia.

Compartir la captura de pantalla de salida

Vamos a crear un nuevo fabricante, puede navegar por la siguiente URL

http://localhost:8000/fabricante/

Compartiendo la captura de pantalla del navegador

Puede escribir el nombre del fabricante (ABB) y hacer clic en el botón POST. El navegador muestra la salida como se muestra a continuación

Finalmente, creemos una nueva entrada para el robot. Puede navegar por la siguiente URL y desplazarse hacia abajo.

http://localhost:8000/robot/

Completemos los datos. Compartiendo la captura de pantalla del navegador para su referencia

Aquí, puede notar que la categoría Robot, Fabricación y Moneda son campos desplegables. Después de completar las entradas, puede hacer clic en el botón POST. Compartiendo debajo de la captura de pantalla de la salida mostrada.

PUT Solicitud HTTP

Editemos el precio del robot que tiene un valor de pk 2. Puede navegar por la siguiente URL y desplazarse hacia abajo. 

http://localhost:8000/robot/2/

Compartiendo la captura de pantalla del navegador. Puede cambiar el precio a 27000 y hacer clic en el botón PONER.

Compartiendo la captura de pantalla de la salida.

ELIMINAR solicitud HTTP

Puede crear una nueva entrada de prueba y explorar la URL con el valor pk. 

http://localhost:8000/robot/2/

Puede notar un botón ELIMINAR. Compartiendo la captura de pantalla del navegador a continuación:

Al hacer clic en el botón Eliminar, el navegador confirma lo mismo. Puede hacer clic en el botón Eliminar en la ventana de confirmación. Compartiendo la captura de pantalla a continuación.

Si la eliminación es exitosa, muestra el siguiente resultado.

Vamos a terminar

A partir de esta sección, entendimos cómo hacer uso de la función de API navegable en el marco de la API REST de Django. Redactamos y enviamos requests HTTP que generan contenido de texto/html como respuesta y también analizamos la respuesta en un navegador web.

Publicación traducida automáticamente

Artículo escrito por SonuGeorge y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *