Vistas basadas en funciones – Django Rest Framework

Django REST Framework nos permite trabajar con vistas regulares de Django. Facilita el procesamiento de requests HTTP y proporciona respuestas HTTP adecuadas. En esta sección, comprenderá cómo implementar las vistas de Django para el servicio web Restful. También hacemos uso del decorador @api_view.

Antes de trabajar en los serializadores Django REST Framework, debe asegurarse de que ya instaló Django y Django REST Framework en su entorno virtual. Puedes consultar los siguientes tutoriales:

A continuación, puede crear un proyecto llamado emt y una aplicación llamada transformers. Consulte los siguientes artículos para comprobar cómo crear un proyecto y una aplicación en Django.

En esta sección, utilizaremos PostgreSQL. Tienes que crear una base de datos llamada emt en PostgreSQL. Puede consultar el siguiente enlace para la instalación.

Instalar PostgreSQL en Windows

Nota: si necesita trabajar con SQLite, puede continuar usando la base de datos predeterminada.

Para hacer uso de PostgreSQL, necesitamos instalar un adaptador de base de datos Python-PostgreSQL (psycopg2). Este paquete ayuda a Django a interactuar con una base de datos PostgreSQL. Puede usar el siguiente comando para instalar el paquete psycopg2. Asegúrese de que la carpeta bin de PostgreSQL esté incluida en las variables ambientales PATH y que el entorno virtual esté activado antes de ejecutar el comando.

pip instalar psycopg2

Ahora, necesita configurar la base de datos PostgreSQL en su proyecto Django. De forma predeterminada, la configuración de la base de datos tiene un motor de base de datos SQLite y un nombre de archivo de base de datos. Puede verificar el archivo de Python setting.py y reemplazar la configuración de la base de datos predeterminada con la configuración de la base de datos PostgreSQL.

DATABASES = {
   'default': {
       'ENGINE': 'django.db.backends.postgresql',
       'NAME': 'emt',
       'USER': 'username',
       'PASSWORD': 'password',
       'HOST': '127.0.0.1',
       'PORT': '5432',
   }
}

Aquí, el nombre se refiere al nombre de la base de datos, el usuario y la contraseña se refieren al nombre de usuario y la contraseña de Postgres.

Por último, necesitamos instalar el paquete httpie en nuestro entorno virtual. Estaremos componiendo comandos HTTPie para la operación CRUD. Puede activar el entorno virtual y ejecutar el siguiente comando

instalación de pip –actualización de httpie

Ahora, creemos el modelo y el serializador.

Creación de modelo y serializador

Antes de entrar en las vistas basadas en clases, creemos un modelo y su serializador, lo que ayuda a demostrar el funcionamiento de las vistas basadas en funciones.

Crear modelo

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 un modelo de Transformador simple en Django, que almacena el nombre del personaje del transformador, el modo alternativo, la descripción y si el personaje está vivo o muerto. Requerimos los siguientes atributos para nuestra entidad Transformador:

  • nombre
  • modo_alterno
  • descripción
  • viva

En un servicio web RESTFul, se accede a cada recurso mediante una URL única, lo que significa que cada empleado tiene su URL única. Y, cada método del modelo se compone de un Verbo HTTP y un Alcance.

Verbo HTTP Alcance Semántica URL
OBTENER Transformador Recuperar un solo transformador http://hostlocal:8000/transformers/{id}/
OBTENER Colección de transformador Recupera todos los transformadores de la colección. http://localhost:8000/transformadores/
CORREO Colección de transformador Crear un nuevo transformador en la colección. http://localhost:8000/transformadores/
PONER Transformador Actualizar un transformador existente http://hostlocal:8000/transformers/{id}/
PARCHE Transformador Actualizar parcialmente un transformador existente http://hostlocal:8000/transformers/{id}/
ELIMINAR Transformador Eliminar un transformador existente http://hostlocal:8000/transformers/{id}/

Entremos en la implementación del modelo Transformer en Django. Puede reemplazar el archivo Python models.py con el siguiente código:

Python3

from django.db import models
  
class Transformer(models.Model):
    name = models.CharField(max_length=150, unique=True)
    alternate_mode = models.CharField(
        max_length=250,
        blank=True,
        null=True)
    description = models.CharField(
        max_length=500,
        blank=True,
        null=True)
    alive = models.BooleanField(default=False)
  
    class Meta:
        ordering = ('name',)
  
    def __str__(self):
        return self.name

El modelo Transformer es una subclase de la clase django.db.models.Model y define los atributos y una clase interna Meta. Tiene un atributo de ordenación que ordena el resultado en orden ascendente según el nombre. Hagamos las migraciones iniciales usando el siguiente comando (asegúrese de haber definido su aplicación (‘transformers.apps.TransformersConfig’) en INSTALLED_APPS en el archivo settings.py Python)

python manage.py hacer migraciones

Luego, aplique todas las migraciones generadas usando el siguiente comando:

python manage.py migrar

La aplicación de migraciones generadas creará una tabla de Transformador en la base de datos.

Creación de serializador

Cree un nuevo archivo Python serializers.py en la carpeta de su aplicación (transformadores) y agregue el siguiente código:

Python3

from rest_framework import serializers
from transformers.models import Transformer
  
class TransformerSerializer(serializers.ModelSerializer):
    class Meta:
        model = Transformer
        fields = "__all__"

Aquí, creamos una clase TransformerSerializer que hereda de rest_framework.serializers.ModelSerializer. Si desea profundizar en los diferentes tipos de serializados, puede consultar Django REST Framework (DRF) Serialization . Ahora es el momento de comenzar nuestro viaje hacia las vistas basadas en funciones. Comenzaremos con las vistas regulares de Django y luego aprovecharemos el decorador @api_view.

Vistas basadas en funciones

Las vistas de Django facilitan el procesamiento de requests HTTP y proporcionan respuestas HTTP. Al recibir una solicitud HTTP, Django crea una instancia de HttpRequest y se pasa como primer argumento a la función de vista. Esta instancia contiene verbos HTTP como GET, POST, PUT, PATCH o DELETE. La función de visualización comprueba el valor y ejecuta el código en función del verbo HTTP. Aquí, el código usa el decorador @csrf_exempt para configurar una cookie CSRF (falsificación de solicitud entre sitios). Esto hace posible publicar en esta vista desde clientes que no tendrán un token CSRF. Entremos en el proceso de implementación. Puede agregar el siguiente código en el archivo views.py.  

Python3

from django.http import HttpResponse, JsonResponse
from django.views.decorators.csrf import csrf_exempt
from rest_framework.parsers import JSONParser
  
from transformers.models import Transformer
from transformers.serializers import TransformerSerializer
  
@csrf_exempt
def transformer_list(request):
    """
    List all transformers, or create a new transformer
    """
    if request.method == 'GET':
        transformer = Transformer.objects.all()
        serializer = TransformerSerializer(transformer, many=True)
        return JsonResponse(serializer.data, safe=False)
  
    elif request.method == 'POST':
        data = JSONParser().parse(request)
        serializer = TransformerSerializer(data=data)
        if serializer.is_valid():
            serializer.save()
            return JsonResponse(serializer.data, status=201)
        return JsonResponse(serializer.errors, status=400)
  
@csrf_exempt
def transformer_detail(request, pk):
    try:
        transformer = Transformer.objects.get(pk=pk)
    except Transformer.DoesNotExist:
        return HttpResponse(status=404)
  
    if request.method == 'GET':
        serializer = TransformerSerializer(transformer)
        return JsonResponse(serializer.data)
  
    elif request.method == 'PUT':
        data = JSONParser().parse(request)
        serializer = TransformerSerializer(transformer, data=data)
  
        if serializer.is_valid():
            serializer.save()
            return JsonResponse(serializer.data)
        return JsonResponse(serializer.errors, status=400)
  
    elif request.method == 'DELETE':
        transformer.delete()
        return HttpResponse(status=204)

Evaluemos el código. Aquí tenemos dos funciones.

  • lista_de_transformadores()
  • transformador_detalle()

lista_de_transformadores()

La función ransformer_list() es capaz de procesar dos verbos HTTP: GET y POST.  

Si el verbo es GET , el código recupera todas las instancias del transformador. 

    if request.method == 'GET':
        transformer = Transformer.objects.all()
        serializer = TransformerSerializer(transformer, many=True)
        return JsonResponse(serializer.data, safe=False)
  • Recupera todos los datos del transformador usando el método objects.all().
  • Serializa las tareas mediante TransformerSerializer.
  • Luego, los datos serializados se procesan usando JsonResponse() y devuelve el resultado

Nota : El argumento many=True especificado serializa varias instancias de Transformer.

Si el verbo es POST , el código crea un nuevo transformador. Aquí, los datos se proporcionan en formato JSON al redactar la solicitud HTTP.

    elif request.method == 'POST':
        data = JSONParser().parse(request)
        serializer = TransformerSerializer(data=data)
        if serializer.is_valid():
            serializer.save()
            return JsonResponse(serializer.data, status=201)
        return JsonResponse(serializer.errors, status=400)
  • Utiliza JSONParser para analizar la solicitud,
  • Serialice los datos analizados usando TransformerSerializer,
  • Si los datos son válidos, se guardan en la base de datos y devuelven el resultado representado con el código de estado.

transformador_detalle()

La función transformer_detail() es capaz de procesar tres verbos HTTP: GET, PUT y DELETE. Si el verbo es GET, el código recupera una única instancia de transformador basada en la clave principal. Si el verbo es PUT, el código actualiza la instancia y la guarda en la base de datos, y si es DELETE, el código elimina la instancia de la base de datos.

Como siguiente paso, debemos enrutar las URL a las vistas. Debe crear un nuevo nombre de archivo de Python urls.py en la carpeta de la aplicación (transformadores) y agregar el siguiente código.

Python3

from django.urls import path
from transformers import views
  
urlpatterns = [
    path('transformers/',
         views.transformer_list,
         name = 'employee-list'),
    path('transformers/<int:pk>/',
         views.transformer_detail,
         name = 'employee-detail'),
]

Ahora, actualicemos la configuración de la URL raíz. Puede agregar el siguiente código al archivo urls.py (la misma carpeta que tiene el archivo settings.py).  

Python3

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

Ahora es el momento de redactar y enviar requests HTTP para probar nuestras vistas.

Vamos a crear una nueva entrada. El comando HTTPie es:

http POST :8000/transformers/ name=”Wheeljack” alternate_mode=”1977 Lancia Stratos Turbo” description=”Siempre inventando nuevas armas y artilugios” living=”Falso”

Producción

HTTP/1.1 201 Created
Content-Length: 152
Content-Type: application/json
Date: Mon, 25 Jan 2021 05:23:10 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.7.5
X-Content-Type-Options: nosniff
X-Frame-Options: DENY

{
    "alive": false,
    "alternate_mode": "1977 Lancia Stratos Turbo",
    "description": "Always inventing new weapons and gadgets",
    "id": 7,
    "name": "Wheeljack"
}

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

Actualicemos el campo vivo del transformador (id=7) a Verdadero. El comando HTTPie es:

http PUT :8000/transformers/7/ name=”Wheeljack” alternate_mode=”1977 Lancia Stratos Turbo” description=”Siempre inventando nuevas armas y artilugios” living=”Verdadero”

Producción

HTTP/1.1 200 OK
Content-Length: 151
Content-Type: application/json
Date: Mon, 25 Jan 2021 05:26:22 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.7.5
X-Content-Type-Options: nosniff
X-Frame-Options: DENY

{
    "alive": true,
    "alternate_mode": "1977 Lancia Stratos Turbo",
    "description": "Always inventing new weapons and gadgets",
    "id": 7,
    "name": "Wheeljack"
}

Recuperemos todos los transformadores. El comando HTTPie es:

http OBTENER :8000/transformadores/

Producción

HTTP/1.1 200 OK
Allow: GET, POST, OPTIONS
Content-Length: 629
Content-Type: application/json
Date: Mon, 25 Jan 2021 05:43:36 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": "1977 Lancia Stratos Turbo",
        "description": "Always inventing new weapons and gadgets",
        "id": 7,
        "name": "Wheeljack"
    },
    {
        "alive": true,
        "alternate_mode": "1979 Porsche 924",
        "description": "Eager and Daring",
        "id": 5,
        "name": "Cliffjumper"
    },
    {
        "alive": true,
        "alternate_mode": "1979 VW Beetle",
        "description": "Small, eager, and brave. 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

@api_view 

@api_view es un decorador en el módulo rest_framework.decorators , y es la clase base para todas las vistas del marco Django REST. Podemos proporcionar los verbos HTTP permitidos como el argumento http_methods_names (lista de strings) en el decorador @api_view . Si el servicio web RESTful recibe un verbo HTTP no compatible, el decorador devuelve una respuesta adecuada en lugar de un error inesperado en Django.     

@api_view(http_method_names=['GET'])

Puede reemplazar el archivo views.py con el siguiente código.

Python3

from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework import status
  
from transformers.models import Transformer
from transformers.serializers import TransformerSerializer
  
@api_view(['GET','POST'])
def transformer_list(request):
    """
    List all transformers, or create a new transformer
    """
    if request.method == 'GET':
        transformer = Transformer.objects.all()
        serializer = TransformerSerializer(transformer, many=True)
        return Response(serializer.data)
  
    elif request.method == 'POST':
        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)
  
@api_view(['GET','PUT','PATCH','DELETE'])
def transformer_detail(request, pk):
    try:
        transformer = Transformer.objects.get(pk=pk)
    except Transformer.DoesNotExist:
        return Response(status=status.HTTP_404_NOT_FOUND)
  
    if request.method == 'GET':
        serializer = TransformerSerializer(transformer)
        return Response(serializer.data)
  
    elif request.method == 'PUT':
        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)
    elif request.method == 'PATCH':
        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)
  
    elif request.method == 'DELETE':
        transformer.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

En el nuevo código, las funciones transformer_list y transformer_detail están envueltas con el decorador @api_vew. La función transformer_list admite los verbos GET y POST, mientras que el método transformer_detail admite los verbos GET, PUT, PATCH y DELETE. Estos verbos admitidos se pasan como parámetros de decorador para cada método. Aquí, eliminamos la clase rest_framework.parsers.JSONParser . De esta manera podemos dejar que el código funcione con diferentes analizadores. También reemplazamos la clase JSONResponse con una clase rest_framework.response.Response más genérica .

Ejecutemos el comando HTTPie con el verbo OPTIONS para enumerar los métodos y verbos admitidos en el método transformer_list.

http OPCIONES :8000/transformadores/

Producción

HTTP/1.1 200 OK
Allow: GET, OPTIONS, POST
Content-Length: 225
Content-Type: application/json
Date: Mon, 25 Jan 2021 16:52:10 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

{
    "description": "List all transformers, or create a new transformer",
    "name": "Transformer List",
    "parses": [
        "application/json",
        "application/x-www-form-urlencoded",
        "multipart/form-data"
    ],
    "renders": [
        "application/json",
        "text/html"
    ]
}

Compartiendo la captura de pantalla del símbolo del sistema

La salida muestra los detalles del método transformer_list. Permite verbos GET, OPTIONS y POST HTTP. También muestra los diferentes análisis y representaciones que admite la función.

Veamos la función transformer_detail. El comando HTTPie es

http OPCIONES :8000/transformers/1/

Producción

HTTP/1.1 200 OK
Allow: OPTIONS, DELETE, GET, PATCH, PUT
Content-Length: 177
Content-Type: application/json
Date: Mon, 25 Jan 2021 16:59:23 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

{
    "description": "",
    "name": "Transformer Detail",
    "parses": [
        "application/json",
        "application/x-www-form-urlencoded",
        "multipart/form-data"
    ],
    "renders": [
        "application/json",
        "text/html"
    ]
}

Puede notar que la función transformer_detail() es compatible con los verbos HTTP OPTIONS, DELETE, GET, PATCH y PUT. También muestra los diferentes análisis y representaciones que admite la función.

El decorador @api_view puede analizar diferentes tipos de contenido eligiendo el analizador apropiado. Del resultado anterior, podemos notar los diferentes analizadores admitidos en el decorador @api_view. Cuando usamos el decorador @api_view, automáticamente hace uso de la clase APIView y su configuración. De esta forma podremos utilizar los analizadores y renders. 

El decorador @api_view ayuda al marco Django REST a examinar el encabezado Content-Type en el atributo de datos e identifica el analizador exacto para analizar la solicitud. También invoca la clase rest_framework.negotiation.DefaultContentNegotiation para seleccionar el renderizador adecuado para la solicitud. 

Ahora es el momento de redactar y enviar diferentes requests HTTP. Vamos a crear una nueva entrada. El comando HTTPie es

http POST :8000/transformers/ name=”Prowl” alternate_mode=”1979 Nissan 280ZX Police Car” description=”Se esfuerza por encontrar la razón y la lógica en todo” living=”Falso”

Producción

HTTP/1.1 201 Created
Allow: GET, POST, OPTIONS
Content-Length: 149
Content-Type: application/json
Date: Mon, 25 Jan 2021 16:18:56 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 Nissan 280ZX Police Car",
    "description": "Strives to find reason and logic in everything",
    "id": 10,
    "name": "Prowl"
}

Compartiendo la captura de pantalla del símbolo del sistema 

Actualicemos el valor del campo vivo a Verdadero. El comando HTTPie es:

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

Producción

HTTP/1.1 200 OK
Allow: PATCH, PUT, DELETE, OPTIONS, GET
Content-Length: 148
Content-Type: application/json
Date: Mon, 25 Jan 2021 16:22:35 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 Nissan 280ZX Police Car",
    "description": "Strives to find reason and logic in everything",
    "id": 10,
    "name": "Prowl"
}

Compartiendo la captura de pantalla del símbolo del sistema

Recuperemos todas las entradas. El comando HTTPie es:

http OBTENER :8000/transformadores/

Producción

HTTP/1.1 200 OK
Allow: GET, POST, OPTIONS
Content-Length: 739
Content-Type: application/json
Date: Mon, 25 Jan 2021 16:23:52 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 Nissan 280ZX Police Car",
        "description": "Strives to find reason and logic in everything",
        "id": 10,
        "name": "Prowl"
    },
    {
        "alive": true,
        "alternate_mode": "1977 Lancia Stratos Turbo",
        "description": "Always inventing new weapons and gadgets",
        "id": 7,
        "name": "Wheeljack"
    },
    {
        "alive": true,
        "alternate_mode": "1979 Porsche 924",
        "description": "Eager and Daring",
        "id": 5,
        "name": "Cliffjumper"
    },
    {
        "alive": true,
        "alternate_mode": "1979 VW Beetle",
        "description": "Small, eager, and brave. 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

En esta sección, entendimos cómo codificar las vistas de Django para procesar la solicitud HTTP y devolver la respuesta HTTP. También nos dimos cuenta de la importancia de envolver nuestras vistas con el decorador @api_view. Finalmente, redactamos y enviamos diferentes requests, incluida la solicitud OPTIONS HTTP, que muestra los verbos, analizadores y renderizadores HTTP admitidos.

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 *