Vistas basadas en clases – Django Rest Framework

Las vistas basadas en clases ayudan a componer fragmentos de comportamiento reutilizables. Django REST Framework proporciona varias vistas prediseñadas que nos permiten reutilizar la funcionalidad común y mantener nuestro código SECO. En esta sección, profundizaremos en las diferentes vistas basadas en clases en Django REST Framework.

Este artículo asume que ya está familiarizado con Django y Django REST Framework. 

Verificar – 

APIView

La clase APIView proporciona el comportamiento comúnmente requerido para la lista estándar y las vistas detalladas. Con la clase APIView, podemos reescribir la vista raíz como una vista basada en clases. Proporcionan métodos de acción como get(), post(), put(), patch() y delete() en lugar de definir los métodos del controlador.

Creando vistas usando APIView

Echemos un vistazo a cómo crear vistas usando APIView. El módulo de archivo views.py de la siguiente manera:

Python3

from django.shortcuts import render
from django.http import Http404
  
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
  
from transformers.models import Transformer
from transformers.serializers import TransformerSerializer
  
class TransformerList(APIView):
    """
    List all Transformers, or create a new Transformer
    """
  
    def get(self, request, format=None):
        transformers = Transformer.objects.all()
        serializer = TransformerSerializer(transformers, many=True)
        return Response(serializer.data)
  
    def post(self, request, format=None):
        serializer = TransformerSerializer(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 TransformerDetail(APIView):
    """
    Retrieve, update or delete a transformer instance
    """
    def get_object(self, pk):
        # Returns an object instance that should 
        # be used for detail views.
        try:
            return Transformer.objects.get(pk=pk)
        except Transformer.DoesNotExist:
            raise Http404
  
    def get(self, request, pk, format=None):
        transformer = self.get_object(pk)
        serializer = TransformerSerializer(transformer)
        return Response(serializer.data)
  
    def put(self, request, pk, format=None):
        transformer = self.get_object(pk)
        serializer = TransformerSerializer(transformer, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
  
    def patch(self, request, pk, format=None):
        transformer = self.get_object(pk)
        serializer = TransformerSerializer(transformer,
                                           data=request.data,
                                           partial=True)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
          
  
    def delete(self, request, pk, format=None):
        transformer = self.get_object(pk)
        transformer.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

El código es similar a las vistas regulares de Django, pero hay una mejor separación entre los diferentes métodos HTTP.

  • El método get() procesa la solicitud HTTP GET
  • El método post() procesa la solicitud HTTP POST
  • El método put() procesa la solicitud HTTP PUT
  • El método patch() procesa la solicitud HTTP PATCH
  • El método delete() procesa la solicitud HTTP DELETE

Establecimiento de la configuración de URL

Dado que estamos utilizando vistas basadas en clases, la forma en que mencionamos las vistas en la ruta del archivo urls.py es ligeramente diferente. Cree un nuevo archivo llamado urls.py (si no existe) en la carpeta de la aplicación (transformadores) y agregue el siguiente código

Python3

from django.urls import path
from rest_framework.urlpatterns import format_suffix_patterns
from transformers import views
  
urlpatterns = [
    path('transformers/', views.TransformerList.as_view()),
    path('transformers/<int:pk>/', views.TransformerDetail.as_view()),
]
  
urlpatterns = format_suffix_patterns(urlpatterns)

A continuación, establezca la configuración de la URL raíz. Puede abrir urls.py (la misma carpeta donde se encuentra el archivo settings.py) y agregar el siguiente código

Python3

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

Redacción y envío de requests HTTP

1. Crea una nueva entrada – 

El comando HTTPie es:

http POST :8000/transformers/ name=”Optimus Prime” alternate_mode=”1979 Freightliner Semi” description=”Optimus Prime es el más fuerte y valiente de todos los Autobots, también es su líder” living=”True”

Producción

HTTP/1.1 201 Created
Allow: GET, POST, HEAD, OPTIONS
Content-Length: 194
Content-Type: application/json
Date: Sat, 23 Jan 2021 03:48:46 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.7.5
Vary: Accept, Cookie
X-Content-Type-Options: nosniff
X-Frame-Options: DENY

{
    "alive": true,
    "alternate_mode": "1979 Freightliner Semi",
    "description": "Optimus Prime is the strongest and most courageous of all Autobots, he is also their leader",
    "id": 1,
    "name": "Optimus Prime"
}

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

2. Recuperar una entrada existente

El valor pk de Optimus Prime es 1. Pasemos el valor pk y recuperemos los detalles

El comando HTTPie es:

http OBTENER: 8000/transformadores/1/

Producción

HTTP/1.1 200 OK
Allow: GET, HEAD, OPTIONS
Content-Length: 194
Content-Type: application/json
Date: Sat, 23 Jan 2021 03:50:42 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.7.5
Vary: Accept, Cookie
X-Content-Type-Options: nosniff
X-Frame-Options: DENY

{
    "alive": true,
    "alternate_mode": "1979 Freightliner Semi",
    "description": "Optimus Prime is the strongest and most courageous of all Autobots, he is also their leader",
    "id": 1,
    "name": "Optimus Prime"
}

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

3. Actualizar una entrada existente

Actualicemos el campo llamado Alive configurándolo en False. El comando HTTPie es:

 http PUT :8000/transformers/1/ name=”Optimus Prime” alternate_mode=”1979 Freightliner Semi” description=”Optimus Prime es el más fuerte y valiente de todos los Autobots, también es su líder” living=”Falso”

Producción

HTTP/1.1 200 OK
Allow: GET, PUT, PATCH, DELETE, HEAD, OPTIONS
Content-Length: 195
Content-Type: application/json
Date: Sat, 23 Jan 2021 04:22:30 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.7.5
Vary: Accept, Cookie
X-Content-Type-Options: nosniff
X-Frame-Options: DENY

{
    "alive": false,
    "alternate_mode": "1979 Freightliner Semi",
    "description": "Optimus Prime is the strongest and most courageous of all Autobots, he is also their leader",
    "id": 1,
    "name": "Optimus Prime"
}

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

4. Actualizar parcialmente una entrada existente

Actualicemos parcialmente el campo llamado descripción. El comando HTTPie es:

http PATCH :8000/transformers/1/ description=”Optimus Prime es el más fuerte, valiente y líder de todos los Autobots”

Producción

HTTP/1.1 200 OK
Allow: GET, PUT, PATCH, DELETE, HEAD, OPTIONS
Content-Length: 181
Content-Type: application/json
Date: Sat, 23 Jan 2021 04:32:40 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.7.5
Vary: Accept, Cookie
X-Content-Type-Options: nosniff
X-Frame-Options: DENY

{
    "alive": false,
    "alternate_mode": "1979 Freightliner Semi",
    "description": "Optimus Prime is the strongest and most courageous and leader of all Autobots",
    "id": 1,
    "name": "Optimus Prime"
}

Compartiendo la captura de pantalla del símbolo del sistema

5. Eliminar una entrada existente

Crearemos una nueva entrada y la eliminaremos. Vamos a crear una entrada de ‘Prueba’ usando el siguiente comando HTTPie:

http POST :8000/transformers/ nombre=”Prueba”

Producción

HTTP/1.1 201 Created
Allow: GET, POST, HEAD, OPTIONS
Content-Length: 77
Content-Type: application/json
Date: Sat, 23 Jan 2021 04:34:41 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.7.5
Vary: Accept, Cookie
X-Content-Type-Options: nosniff
X-Frame-Options: DENY

{
    "alive": false,
    "alternate_mode": null,
    "description": null,
    "id": 2,
    "name": "Test"
}

Ahora eliminemos la entrada ‘Prueba’ (pk =2). El comando HTTPie para eliminar la entrada es

http ELIMINAR: 8000/transformadores/2/

Producción

HTTP/1.1 204 No Content
Allow: GET, PUT, PATCH, DELETE, HEAD, OPTIONS
Content-Length: 0
Date: Sat, 23 Jan 2021 04:35:06 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.7.5
Vary: Accept, Cookie
X-Content-Type-Options: nosniff
X-Frame-Options: DENY

Compartiendo la captura de pantalla del símbolo del sistema

mezclas

Las clases mixtas nos permiten componer fragmentos de comportamiento reutilizables. Se pueden importar desde rest_framework.mixins. Analicemos los diferentes tipos de clases mixtas.

  • ListModelMixin : proporciona un método .list(request, *args, **kwargs) para enumerar un conjunto de consultas. Si se completa el conjunto de consultas, el cuerpo de la respuesta tiene una respuesta 200 OK con una representación serializada del conjunto de consultas.
  • CreateModelMixin : proporciona un método .create(request, *args, **kwargs) para crear y guardar una nueva instancia de modelo. Si se crea el objeto, el cuerpo de la respuesta tiene una respuesta 201 Creado , con una representación serializada del objeto. Si no es válido, devuelve una   respuesta de solicitud incorrecta 400 con los detalles del error.
  • RetrieveModelMixin : proporciona un método .retrieve(request, *args, **kwargs) para devolver una instancia de modelo existente en una respuesta. Si se puede recuperar un objeto, el cuerpo de la respuesta tiene una respuesta 200 OK , con una representación serializada del objeto. De lo contrario, devolverá un 404 No encontrado .
  • UpdateModelMixin : proporciona un método .update(request, *args, **kwargs) para actualizar y guardar una instancia de modelo existente. También proporciona un método .partial_update(request, *args, **kwargs) para actualizar parcialmente una instancia de modelo existente. . Si el objeto se actualiza, el cuerpo de la respuesta tiene una respuesta 200 OK , con una representación serializada del objeto. De lo contrario, se devolverá la respuesta 400 Bad Request con los detalles del error.
  • DestroyModelMixin : proporciona un método .destroy(request, *args, **kwargs) para eliminar una instancia de modelo existente. Si se elimina un objeto, el cuerpo de la respuesta tiene una respuesta 204 Sin contenido ; de lo contrario, devolverá un 404 No encontrado .

Nota: Usaremos GenericAPIView para crear nuestras vistas y agregar Mixins. 

Creación de vistas usando Mixins

Echemos un vistazo a cómo podemos hacer uso de las clases de Mixin. El módulo de archivo views.py de la siguiente manera:

Python3

from rest_framework import mixins
from rest_framework import generics
from transformers.models import Transformer
from transformers.serializers import TransformerSerializer
  
class TransformerList(mixins.ListModelMixin,
                      mixins.CreateModelMixin,
                      generics.GenericAPIView):
    queryset = Transformer.objects.all()
    serializer_class = TransformerSerializer
  
    def get(self, request, *args, **kwargs):
        return self.list(request, *args, **kwargs)
  
    def post(self, request, *args, **kwargs):
        return self.create(request, *args, **kwargs)
  
class TransformerDetail(mixins.RetrieveModelMixin,
                        mixins.UpdateModelMixin,
                        mixins.DestroyModelMixin,
                        generics.GenericAPIView):
    queryset = Transformer.objects.all()
    serializer_class = TransformerSerializer
  
    def get(self, request, *args, **kwargs):
        return self.retrieve(request, *args, **kwargs)
  
    def put(self, request, *args, **kwargs):
        return self.update(request, *args, **kwargs)
  
    def patch(self, request, *args, **kwargs):
        return self.partial_update(request, *args, **kwargs)
  
    def delete(self, request, *args, **kwargs):
        return self.destroy(request, *args, **kwargs)

Aquí, la clase GenericAPIView proporciona la funcionalidad principal y le estamos agregando clases mixtas. Queryset y serializer_class son los atributos básicos de la clase GenericAPIView . El atributo queryset se usa para devolver objetos desde esta vista y el atributo serializer_class se usa para validar, deserializar entradas y serializar salidas.

En la clase TransformerList, utilizamos clases mixtas que proporcionan acciones .list() y .create() y vinculan las acciones a los métodos get() y post(). En la clase TransformerDetail hacemos uso de clases mixtas que proporcionan .retrieve(), .update(), .partial_update() y . acciones destroy() y vincule las acciones a los métodos get(), put(), patch() y delete().

Redacción y envío de requests HTTP

1. Crea una nueva entrada

El comando HTTPie es

http POST :8000/transformers/ name=”Bumblebee” alternate_mode=”1979 VW Beetle” description=”Pequeño, entusiasta y valiente, Bumblebee actúa como mensajero, explorador y espía” living=”Verdadero”

Producción

HTTP/1.1 201 Created
Allow: GET, POST, HEAD, OPTIONS
Content-Length: 161
Content-Type: application/json
Date: Sat, 23 Jan 2021 04:58:26 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.7.5
Vary: Accept, Cookie
X-Content-Type-Options: nosniff
X-Frame-Options: DENY

{
    "alive": true,
    "alternate_mode": "1979 VW Beetle",
    "description": "Small, eager, and brave, Bumblebee acts as a messenger, scout, and spy",
    "id": 3,
    "name": "Bumblebee"
}

2. Recuperar todas las entradas

El comando HTTPie es

http OBTENER :8000/transformadores/

Producción

HTTP/1.1 200 OK
Allow: GET, POST, HEAD, OPTIONS
Content-Length: 345
Content-Type: application/json
Date: Sat, 23 Jan 2021 04:59:42 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.7.5
Vary: Accept, Cookie
X-Content-Type-Options: nosniff
X-Frame-Options: DENY

[
    {
        "alive": true,
        "alternate_mode": "1979 VW Beetle",
        "description": "Small, eager, and brave, Bumblebee acts as a messenger, scout, and spy",
        "id": 3,
        "name": "Bumblebee"
    },
    {
        "alive": false,
        "alternate_mode": "1979 Freightliner Semi",
        "description": "Optimus Prime is the strongest and most courageous and leader of all Autobots",
        "id": 1,
        "name": "Optimus Prime"
    }
]

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

Vistas genéricas basadas en clases

Para hacer uso de vistas genéricas basadas en clases, las clases de vista deben importarse desde rest_framework.generics.

  • CreateAPIView : proporciona un controlador de método de publicación y se usa para puntos finales de solo creación. CreateAPIView amplía GenericAPIView y CreateModelMixin
  • ListAPIView : proporciona un controlador de método get y se usa para puntos finales de solo lectura para representar una colección de instancias de modelo. ListAPIView amplía GenericAPIView y ListModelMixin.
  • RetrieveAPIView : proporciona un controlador de método get y se usa para puntos finales de solo lectura para representar una sola instancia de modelo. RetrieveAPIView amplía GenericAPIView y RetrieveModelMixin.
  • DestroyAPIView : proporciona un controlador de método de eliminación y se usa para puntos finales de solo eliminación para una sola instancia de modelo. DestroyAPIView amplía GenericAPIView y DestroyModelMixin.
  • UpdateAPIView : proporciona controladores de métodos de colocación y parches y se usa para puntos finales de solo actualización para una sola instancia de modelo. UpdateAPIView amplía GenericAPIView y UpdateModelMixin.
  • ListCreateAPIView : proporciona controladores de métodos de obtención y publicación y se usa para puntos finales de lectura y escritura para representar una colección de instancias de modelo. ListCreateAPIView amplía GenericAPIView, ListModelMixin y CreateModelMixin.
  • RetrieveUpdateAPIView : proporciona controladores de métodos get, put y patch. Se utiliza para leer o actualizar puntos finales para representar una sola instancia de modelo. RetrieveUpdateAPIView amplía GenericAPIView, RetrieveModelMixin y UpdateModelMixin.
  • RetrieveDestroyAPIView : proporciona controladores de métodos de obtención y eliminación y se usa para leer o eliminar puntos finales para representar una sola instancia de modelo. RetrieveDestroyAPIView amplía GenericAPIView, RetrieveModelMixin y DestroyModelMixin.
  • RetrieveUpdateDestroyAPIView : proporciona controladores de métodos get, put, patch y delete. Se utiliza para puntos finales de lectura, escritura y eliminación para representar una sola instancia de modelo. Extiende GenericAPIView, RetrieveModelMixin, UpdateModelMixin y DestroyModelMixin.

Creación de vistas mediante vistas genéricas basadas en clases

Echemos un vistazo a cómo podemos hacer uso de las clases de Mixin. Aquí aprovecharemos ListCreateAPIView y RetrieveUpdateDestroyAPIView. El módulo de archivo views.py de la siguiente manera:

Python3

from rest_framework import generics
  
from transformers.models import Transformer
from transformers.serializers import TransformerSerializer
  
class TransformerList(generics.ListCreateAPIView):
    queryset = Transformer.objects.all()
    serializer_class = TransformerSerializer
  
class TransformerDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Transformer.objects.all()
    serializer_class = TransformerSerializer

Puede notar que pudimos evitar una gran cantidad de código repetitivo. Estas vistas genéricas combinan fragmentos de comportamiento reutilizables de las clases mixtas. Veamos la declaración de ListCreateAPIView y RetrieveUpdateDestroyAPIView:

class ListCreateAPIView(mixins.ListModelMixin,
                        mixins.CreateModelMixin,
                        GenericAPIView):
   ......

class RetrieveUpdateDestroyAPIView(mixins.RetrieveModelMixin,
                                   mixins.UpdateModelMixin,
                   mixins.DestroyModelMixin,
                                   GenericAPIView):
  ......

Redacción y envío de requests HTTP

1. Crea una nueva entrada

El comando HTTPie es

http POST :8000/transformers/ name=”Cliffjumper” alternate_mode=”1979 Porsche 924″ description=”Su entusiasmo y audacia no tienen igual” living=”True”

Producción

HTTP/1.1 201 Created
Allow: GET, POST, HEAD, OPTIONS
Content-Length: 133
Content-Type: application/json
Date: Sat, 23 Jan 2021 05:28:45 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.7.5
Vary: Accept, Cookie
X-Content-Type-Options: nosniff
X-Frame-Options: DENY

{
    "alive": true,
    "alternate_mode": "1979 Porsche 924",
    "description": "His eagerness and daring have no equal",
    "id": 5,
    "name": "Cliffjumper"
}

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

2. Actualizar una entrada existente

El comando HTTPie es

http PUT :8000/transformers/5/ name=”Cliffjumper” alternate_mode=”1979 Porsche 924″ description=”Ansioso y audaz” vivo=”Verdadero”

Producción

HTTP/1.1 200 OK
Allow: GET, PUT, PATCH, DELETE, HEAD, OPTIONS
Content-Length: 111
Content-Type: application/json
Date: Sat, 23 Jan 2021 05:35:39 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.7.5
Vary: Accept, Cookie
X-Content-Type-Options: nosniff
X-Frame-Options: DENY

{
    "alive": true,
    "alternate_mode": "1979 Porsche 924",
    "description": "Eager and Daring",
    "id": 5,
    "name": "Cliffjumper"
}

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

3. Actualizar parcialmente una entrada existente

http PARCHE: 8000/transformers/3/alive=”Verdadero”

Producción

HTTP/1.1 200 OK
Allow: GET, PUT, PATCH, DELETE, HEAD, OPTIONS
Content-Length: 151
Content-Type: application/json
Date: Sat, 23 Jan 2021 05:37:54 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.7.5
Vary: Accept, Cookie
X-Content-Type-Options: nosniff
X-Frame-Options: DENY

{
    "alive": true,
    "alternate_mode": "1979 VW Beetle",
    "description": "Small, eager, and brave. Acts as a messenger, scout, and spy",
    "id": 3,
    "name": "Bumblebee"
}

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

En esta sección, exploramos diferentes tipos de vistas basadas en clases proporcionadas por Django REST Framework. Implementamos vistas usando APIView y explicamos diferentes tipos de clases mixtas. Finalmente, revelamos varios tipos de vistas genéricas basadas en clases y demostramos cómo evitan una gran cantidad de código repetitivo.

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 *