La serialización es uno de los conceptos más importantes en los servicios web RESTful. Facilita la conversión de datos complejos (como instancias de modelos) a tipos de datos nativos de Python que se pueden representar mediante JSON, XML u otros tipos de contenido. En Django REST Framework, tenemos diferentes tipos de serializadores para serializar instancias de objetos, y los serializadores tienen diferentes relaciones de serializador para representar relaciones de modelos. En esta sección, discutiremos las diferentes relaciones de serializador proporcionadas por Django REST Framework Serializers.
Tabla de contenido
Empezando
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 (herramienta de administración de empleados) y una aplicación llamada empleados. 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
Creación de modelos y vistas de Django
Crear modelos de Django
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 Employee y un modelo EmployeeTask en Django. El modelo EmployeeTask tiene una relación ManyToOne con el modelo Employee. Requerimos los siguientes atributos para nuestra entidad Employee:
- emp_id
- nombre
- género
- designacion
Los atributos de nuestro modelo EmployeeTask son los siguientes:
- nombre de la tarea
- empleado (clave externa – Empleado)
- task_desc
- Fecha de creación
- plazo
Entremos en la implementación del modelo Employee en Django. Puede reemplazar el archivo Python models.py con el siguiente código:
Python3
GENDER_CHOICES = (('M','Male'), ('F','Female'),) class Employee(models.Model): emp_id = models.IntegerField() name = models.CharField(max_length=150) gender = models.CharField(max_length=1, choices=GENDER_CHOICES, default='M') designation = models.CharField(max_length=150) class Meta: ordering=('emp_id',) def __str__(self): return self.name
El modelo Employee 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 la identificación del empleado.
A continuación, entremos en la implementación del modelo EmployeeTask. Puede agregar el siguiente código al archivo models.py.
Python3
class EmployeeTask(models.Model): task_name = models.CharField(max_length=150) employee = models.ForeignKey(Employee, related_name='tasks', on_delete=models.CASCADE) task_desc = models.CharField(max_length=350) created_date = models.DateTimeField(auto_now_add=True) deadline = models.DateTimeField() class Meta: ordering = ('task_name',) def __str__(self): return self.task_name
El modelo EmployeeTask 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 nombre_tarea. Tiene un campo de empleado que tiene una relación de muchos a uno con el modelo Empleado.
employee = models.ForeignKey(Employee, related_name='tasks', on_delete=models.CASCADE)
El related_name ayuda en una relación inversa. Relación inversa significa referirse de Empleado a TareaEmpleado. El campo de empleado representa el modelo de empleado en EmployeeTaks. Del mismo modo, related_name representa EmployeeTask en el modelo Employee.
La clase de serializador no incluye automáticamente las relaciones inversas. Debemos agregarlo explícitamente a la lista de campos. Si establece un argumento de nombre relacionado apropiado en la relación, puede usarlo como un nombre de campo (podrá comprender la relación inversa mientras serializa los modelos).
Hagamos las migraciones iniciales usando el siguiente comando.
python manage.py hacer migraciones
Si la migración es exitosa, aplique todas las migraciones generadas usando el siguiente comando:
python manage.py migrar
Si tiene éxito, puede verificar las entradas de su base de datos. Ahora, vamos a crear las vistas de Django.
Creación de vistas
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. 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.
Puede agregar el siguiente código a su archivo view.py.
Python3
from django.shortcuts import render from django.http import HttpResponse, JsonResponse from django.views.decorators.csrf import csrf_exempt from rest_framework.renderers import JSONRenderer from rest_framework.parsers import JSONParser from employees.models import Employee, EmployeeTask from employees.serializers import EmployeeSerializer, EmployeeTaskSerializer @csrf_exempt def employee_list(request): if request.method == 'GET': emp = Employee.objects.all() emp_serializer = EmployeeSerializer(emp, many=True) return JsonResponse(emp_serializer.data, safe=False) elif request.method == 'POST': emp_data = JSONParser().parse(request) emp_serializer = EmployeeSerializer(data=emp_data) if emp_serializer.is_valid(): emp_serializer.save() return JsonResponse(emp_serializer.data, status=201) return JsonResponse(emp_serializer.errors, status=400) @csrf_exempt def employee_detail(request, pk): try: emp = Employee.objects.get(pk=pk) except Employee.DoesNotExist: return HttpResponse(status=404) if request.method == 'GET': emp_serializer = EmployeeSerializer(emp) return JsonResponse(emp_serializer.data) elif request.method == 'DELETE': emp.delete() return HttpResponse(status=204) @csrf_exempt def employeetask_list(request): if request.method == 'GET': emptask = EmployeeTask.objects.all() emptask_serializer = EmployeeTaskSerializer(emptask, many=True) return JsonResponse(emptask_serializer.data, safe=False) elif request.method == 'POST': emptask_data = JSONParser().parse(request) emptask_serializer = EmployeeTaskSerializer(data=emptask_data) if emptask_serializer.is_valid(): emptask_serializer.save() return JsonResponse(emptask_serializer.data, status=201) return JsonResponse(emptask_serializer.errors, status=400) @csrf_exempt def employeetask_detail(request, pk): try: emptask = EmployeeTask.objects.get(pk=pk) except EmployeeTask.DoesNotExist: return HTTPResponse(status=404) if request.method == 'GET': emptask_serializer = EmployeeTaskSerializer(emptask) return JsonResponse(emptask_serializer.data) elif request.method == 'DELETE': emptask.delete() return HttpResponse(status=204)
Aquí, tenemos diferentes funciones para procesar requests relacionadas con el modelo Employee y el modelo EmployeeTask: employee_list, employeetask_list, y employee_detail y employeetask_detail. Las funciones employee_list y employeetask_list son capaces de procesar requests para recuperar todos los empleados y tareas de empleados o para crear un nuevo empleado y crear una nueva tarea de empleado. Las funciones employee_detail y employeetask_detail son capaces de procesar requests como recuperar una entrada en particular y eliminar una entrada.
Establecimiento de la configuración de URL
Ahora, es necesario enrutar las URL para ver. Debe crear un nuevo nombre de archivo de Python urls.py en la carpeta de la aplicación (empleados) y agregar el siguiente código.
Python3
from django.urls import path from employees import views urlpatterns = [ path('employees/', views.employee_list, name = 'employee-list'), path('employees/<int:pk>/', views.employee_detail, name='employee-detail'), path('task/', views.employeetask_list, name = 'employeetask-list'), path('task/<int:pk>/', views.employeetask_detail, name='employeetask-detail'),
En función de la ruta coincidente, las direcciones URL se enrutan a las vistas correspondientes. A continuación, debemos reemplazar el código en el archivo urls.py en la carpeta raíz (emt\emt\urls.py). En la actualidad, tiene las configuraciones de URL raíz. Actualice el archivo urls.py con el siguiente código.
Python3
from django.urls import path, include urlpatterns = [ path('', include('employees.urls')), ]
Campo relacionado con la clave principal
PrimaryKeyRelatedField representa el objetivo de la relación utilizando la clave principal (pk). Se puede lograr generando la relación usando el campo De forma predeterminada, este campo es de lectura y escritura, pero puede convertirlo en solo lectura configurando el atributo read_only en True. El PrimaryKeyRelatedField tiene los siguientes argumentos:
- queryset: se usa para búsquedas de instancias de modelos al validar la entrada del campo. Las relaciones deben establecer explícitamente un conjunto de consultas ( ) o establecer read_only=True.
- many: establezca este argumento en True para serializar más de una relación
- allow_null: si se establece en Verdadero, el campo aceptará valores de Ninguno o la string vacía para relaciones anulables. El valor predeterminado es falso.
- pk_field: establezca en un campo para controlar la serialización/deserialización del valor de la clave principal. Por ejemplo, pk_field=UUIDField(format=’hex’) serializaría una clave principal UUID en su representación hexadecimal compacta.
Ahora vayamos a nuestro código serializador. Aquí tenemos dos clases de serializador: EmployeeSerializer y EmployeeTaskSerializer. La clase EmployeeSerializer serializa el modelo Employee y EmployeeTaskSerializer serializa el modelo EmployeeTask. El modelo EmployeeTask mantiene una relación ManyToOne con el modelo Employee.
employee = models.ForeignKey(Employee, related_name='tasks', on_delete=models.CASCADE)
No se asignará la misma tarea a más de un empleado, pero un empleado puede tener varias tareas. Por lo tanto, la clase EmployeeTaskSerializer debe serializar solo una única instancia de empleado, mientras que la clase EmployeeSerializer debe serializar una o más instancias de EmployeeTask (se puede asignar más de una tarea a un empleado).
El proceso del generador de relaciones en EmployeeTaskSerializer de la siguiente manera:
employee = serializers.PrimaryKeyRelatedField(queryset=Employee.objects.all(), many=False)
De forma predeterminada, el campo PrimaryKeyRelatedField tiene permiso de lectura y escritura. El argumento busca la instancia de modelo particular en la tabla Empleado. El argumento se establece porque solo hay una única relación para serializar.
El proceso del generador de relaciones en la clase EmployeeSerializer de la siguiente manera:
tasks = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
El atributo de tareas es el nombre_relacionado especificado (relación de clave externa) en el modelo EmployeeTask. Dado que cada empleado puede tener más de una tarea, configuramos read_only=True solo otorga permiso para recuperar la tarea del empleado.
Puede agregar el siguiente código al archivo serializers.py. (si no tiene el archivo, puede crear un archivo llamado serializers.py en la carpeta [empleados] de su aplicación).
Python3
from rest_framework import serializers from employees.models import Employee, EmployeeTask class EmployeeSerializer(serializers.ModelSerializer): # PrimaryKeyRelatedField tasks = serializers.PrimaryKeyRelatedField(many=True, read_only=True) class Meta: model = Employee fields = ( 'pk', 'emp_id', 'name', 'gender', 'designation', 'tasks') class EmployeeTaskSerializer(serializers.ModelSerializer): # PrimaryKeyRelatedField employee = serializers.PrimaryKeyRelatedField(queryset=Employee.objects.all(), many=False) class Meta: model = EmployeeTask fields = ( 'pk', 'task_name', 'employee', 'task_desc', 'created_date', 'deadline')
Completemos la tabla de empleados. Puede ejecutar el siguiente comando HTTPie.
http POST :8000/employees/ emp_id=128 nombre=”Mathew A” género=”M” designación=”Ingeniero de Software”
Producción
HTTP/1.1 201 Created Content-Length: 140 Content-Type: application/json Date: Thu, 21 Jan 2021 09:16:50 GMT Referrer-Policy: same-origin Server: WSGIServer/0.2 CPython/3.7.5 X-Content-Type-Options: nosniff X-Frame-Options: DENY { "designation": "Software Engineer", "emp_id": 128, "gender": "M", "name": "Mathew A", "pk": 8, "tasks": [] }
Puede notar el valor pk del empleado. Ahora, creemos una tarea de empleado y asignémosla al empleado usando PrimaryKeyRelatedField. Aquí, el valor de la clave principal del empleado llamado Mathew A es 8. Debe pasarlo al nombre de campo empleado. Ejecute el siguiente comando HTTPie.
http :8000/task/ task_name=”Intercambiar el primer y último elemento de una lista” employee=8 task_desc=”Escribir un programa de Python para intercambiar el primer y último elemento de una lista” fecha límite=”2021-01-25 00:00: 00.000000+00:00″
Producción
HTTP/1.1 201 Created Content-Length: 285 Content-Type: application/json Date: Thu, 21 Jan 2021 09:42:39 GMT Referrer-Policy: same-origin Server: WSGIServer/0.2 CPython/3.7.5 X-Content-Type-Options: nosniff X-Frame-Options: DENY { "created_date": "2021-01-21T09:42:39.792788Z", "deadline": "2021-01-25T00:00:00Z", "employee": 8, "task_desc": "Write a Python program to interchange first and last element in a list", "task_name": "Interchange first and last elements in a list" }
Puede crear una tarea más y asignarla al mismo empleado y procesar la solicitud para recuperar los detalles del empleado. El comando HTTPie es
http :8000/empleados/
Producción
HTTP/1.1 200 OK Content-Length: 219 Content-Type: application/json Date: Fri, 22 Jan 2021 03:58:01 GMT Referrer-Policy: same-origin Server: WSGIServer/0.2 CPython/3.7.5 X-Content-Type-Options: nosniff X-Frame-Options: DENY [ { "designation": "Software Engineer", "emp_id": 128, "gender": "M", "name": "Mathew A", "pk": 8, "tasks": [ 2, 1 ] }, { "designation": "Test Engineer", "emp_id": 129, "gender": "F", "name": "Jeena R", "pk": 9, "tasks": [] } ]
Compartiendo la captura de pantalla del símbolo del sistema para su referencia
Puede observar el campo de tareas para el empleado llamado Mathew A. Muestra el pk del modelo de tarea y el argumento identificador de instancia de tarea múltiple serializado.
Recuperemos los detalles de la tarea usando el siguiente comando HTTPie
http :8000/tarea/
Producción
HTTP/1.1 200 OK Content-Length: 454 Content-Type: application/json Date: Fri, 22 Jan 2021 03:59:40 GMT Referrer-Policy: same-origin Server: WSGIServer/0.2 CPython/3.7.5 X-Content-Type-Options: nosniff X-Frame-Options: DENY [ { "created_date": "2021-01-21T09:48:47.710707Z", "deadline": "2021-01-27T00:00:00Z", "employee": 8, "pk": 2, "task_desc": "Write a Python program for Binary Search", "task_name": "Binary Search" }, { "created_date": "2021-01-21T09:42:39.792788Z", "deadline": "2021-01-25T00:00:00Z", "employee": 8, "pk": 1, "task_desc": "Write a Python program to interchange first and last element in a list", "task_name": "Interchange first and last elements in a list" } ]
Compartiendo la captura de pantalla del símbolo del sistema para su referencia
Veamos el comando HTTPie para crear una nueva tarea.
http :8000/task/ task_name=”PrimaryKeyRelatedField” employee=8 task_desc=”Serializar relación usando PrimaryKeyRelateField” fecha límite=”2021-01-27 00:00:00.000000+00:00″
Producción
HTTP/1.1 201 Created Content-Length: 213 Content-Type: application/json Date: Fri, 22 Jan 2021 04:33:15 GMT Referrer-Policy: same-origin Server: WSGIServer/0.2 CPython/3.7.5 X-Content-Type-Options: nosniff X-Frame-Options: DENY { "created_date": "2021-01-22T04:33:15.855264Z", "deadline": "2021-01-27T00:00:00Z", "employee": 8, "pk": 6, "task_desc": "Serialize relationship using PrimaryKeyRelateField", "task_name": "PrimaryKeyRelatedField" }
Compartiendo la captura de pantalla del símbolo del sistema para su referencia:
Ahora exploremos cómo StringRelatedField representa una relación.
CampoRelacionadoDeString
StringRelatedField representa el objetivo de la relación utilizando su método __str__. Este campo es de solo lectura y establece el argumento ‘muchos’ en verdadero si hay más de una instancia para serializar. Hagamos uso de StringRelatedField para tareas archivadas en la clase EmployeeSerializer. El proceso del generador de relaciones es el siguiente:
tasks = serializers.StringRelatedField(many=True)
La clase EmployeeSerializer de la siguiente manera:
Python3
class EmployeeSerializer(serializers.ModelSerializer): # StringRelatedField tasks = serializers.StringRelatedField(many=True) class Meta: model = Employee fields = ( 'pk', 'emp_id', 'name', 'gender', 'designation', 'tasks')
Recuperemos los detalles del empleado para comprender cómo StringRelatedField muestra los valores del campo de relación. El comando HTTPie para recuperar los valores de los empleados es:
http :8000/empleados/
Producción
HTTP/1.1 200 OK Content-Length: 279 Content-Type: application/json Date: Fri, 22 Jan 2021 04:04:08 GMT Referrer-Policy: same-origin Server: WSGIServer/0.2 CPython/3.7.5 X-Content-Type-Options: nosniff X-Frame-Options: DENY [ { "designation": "Software Engineer", "emp_id": 128, "gender": "M", "name": "Mathew A", "pk": 8, "tasks": [ "Binary Search", "Interchange first and last elements in a list" ] }, { "designation": "Test Engineer", "emp_id": 129, "gender": "F", "name": "Jeena R", "pk": 9, "tasks": [] } ]
Compartiendo la captura de pantalla del símbolo del sistema para su referencia
Aquí puede notar que el campo de tareas muestra el valor de string de la función en el modelo EmployeeTask.
def __str__(self): return self.task_name
SlugRelatedField
SlugRelatedField representa el destino de la relación mediante un campo en el destino. De forma predeterminada, el campo permite la operación de lectura y escritura. Para operaciones de escritura, el campo slug que representa un campo de modelo debe ser único. SlugRelatedField tiene los siguientes argumentos:
- slug_field : un campo en el objetivo y debe identificar de forma única cualquier instancia dada.
- queryset : facilita las búsquedas de instancias de modelos al validar la entrada de campo. Las relaciones deben establecer explícitamente un conjunto de consultas o establecer read_only=True.
- many : establezca este argumento en True para serializar más de una relación
- allow_null : si se establece en Verdadero, el campo aceptará valores de Ninguno o la string vacía para relaciones anulables. El valor predeterminado es falso.
En la clase EmployeeTaskSerializer, puede reemplazar la representación del campo del empleado con el siguiente código:
employee = serializers.SlugRelatedField( queryset=Employee.objects.all(), slug_field='name')
El código EmployeeTaskSerializer de la siguiente manera:
Python3
class EmployeeTaskSerializer(serializers.ModelSerializer): # SlugRelatedField employee = serializers.SlugRelatedField( queryset=Employee.objects.all(), slug_field='name') class Meta: model = EmployeeTask fields = ( 'pk', 'task_name', 'employee', 'task_desc', 'created_date', 'deadline')
El comando HTTPie para crear una nueva tarea de empleado es
http :8000/task/ task_name=”SlugRelatedField” employee=”Mathew A” task_desc=”Serializar relación usando SlugRelateField” fecha límite=”2021-01-27 00:00:00.000000+00:00″
Producción
HTTP/1.1 201 Created Content-Length: 210 Content-Type: application/json Date: Fri, 22 Jan 2021 04:41:12 GMT Referrer-Policy: same-origin Server: WSGIServer/0.2 CPython/3.7.5 X-Content-Type-Options: nosniff X-Frame-Options: DENY { "created_date": "2021-01-22T04:41:12.424001Z", "deadline": "2021-01-27T00:00:00Z", "employee": "Mathew A", "pk": 7, "task_desc": "Serialize relationship using SlugRelateField", "task_name": "SlugRelatedField" }
Compartiendo la captura de pantalla del símbolo del sistema para su referencia
Aquí, al crear una nueva tarea, le hemos dado el nombre del empleado en el campo del empleado en lugar de la clave principal. También puede mencionar la identificación del empleado mientras representa a SlugRelatedField. Debe asegurarse de que satisfaga la restricción única.
HyperlinkedIndetityField
Para hipervincular la API, la clase de serializador debe extender HyperlinkedModelSerializer. La clase HyperlinkedModelSerializer utiliza hipervínculos para representar relaciones, en lugar de claves principales. De forma predeterminada, la clase de serializador que se hereda de la clase HyperlinkedModelSerializer incluirá un campo de dirección URL en lugar de un campo de clave principal. El campo URL se representará mediante un campo serializador HyperlinkedIdentityField. También se puede utilizar para un atributo en el objeto.
HyperlinkedIdentityField siempre es de solo lectura. Los argumentos de HyperlinkedIdentitField son:
- view_name : el nombre de la vista se utiliza como destino de la relación. En las clases de enrutadores estándar, será una string con el formato <nombre_del_modelo>-detalle.
- lookup_field : el campo en el destino, que se utiliza para la búsqueda. Corresponde a un argumento de palabra clave de URL en la vista a la que se hace referencia. El valor predeterminado es ‘pk’.
- lookup_url_kwarg : el nombre del argumento de palabra clave definido en la URL conf que corresponde al campo de búsqueda. El valor predeterminado es usar el mismo valor que lookup_field.
- formato : si se usan sufijos de formato, los campos con hipervínculos usarán el mismo sufijo de formato para el destino, a menos que se anule con el argumento de formato.
En la clase EmployeeTaskSerializer, puede representar el campo de URL como se muestra a continuación:
url = serializers.HyperlinkedIdentityField( view_name='employeetask-detail', lookup_field='pk' )
Nota: De forma predeterminada, la clase de serializador que se hereda de la clase HyperlinkedModelSerializer incluirá un campo de URL y el nombre de la vista será una string con el formato <model_name>-detail.
La clase EmployeeTaskSerializer de la siguiente manera:
Python3
class EmployeeTaskSerializer(serializers.HyperlinkedModelSerializer): url = serializers.HyperlinkedIdentityField( view_name='employeetask-detail', lookup_field='pk' ) employee = serializers.SlugRelatedField( queryset=Employee.objects.all(), slug_field='name') class Meta: model = EmployeeTask fields = '__all__'
Al crear una instancia de HyperlinkedModelSerializer, es imprescindible incluir la solicitud actual en el contexto del serializador. Debe pasar context={‘request’:request} como argumento al crear una instancia de su EmployeeTaskSerializer. Por ejemplo:
emp_serializer = EmployeeSerializer(emp, many=True, context={'request':request})
Asegúrese de editar su función employee_list y employee_detail en el archivo views.py con el código anterior. Debe agregar el argumento context={‘request’:request} al instanciar EmployeeTaskSerializer (GET, POST, PUT y PATCH).
Nota: Nota: este contexto, junto con el campo de búsqueda, se utiliza para generar una URL completa mediante HyperlinkedIdentityField.
Recuperemos los valores de EmployeeTask para comprender cómo se muestran los valores. El comando HTTPie es
http OBTENER :8000/tarea/1/
Producción
HTTP/1.1 200 OK Content-Length: 296 Content-Type: application/json Date: Fri, 22 Jan 2021 16:16:42 GMT Referrer-Policy: same-origin Server: WSGIServer/0.2 CPython/3.7.5 X-Content-Type-Options: nosniff X-Frame-Options: DENY { "created_date": "2021-01-21T09:42:39.792788Z", "deadline": "2021-01-25T00:00:00Z", "employee": "Mathew A", "task_desc": "Write a Python program to interchange first and last element in a list", "task_name": "Interchange first and last elements in a list", "url": "http://localhost:8000/task/1/" }
Compartiendo la captura de pantalla del símbolo del sistema para su referencia
Si analizamos la salida, podemos notar que en lugar de la clave principal muestra el campo url.
"url": "http://localhost:8000/task/1/"
Campo relacionado hipervinculado
HyperlinkedRelatedField se utiliza para representar el objetivo de la relación mediante un hipervínculo. De forma predeterminada, este campo es de lectura y escritura, pero podemos hacerlo de solo lectura configurando el indicador de solo lectura como True. Los argumentos de HyperlinkedRelatedField son los siguientes:
- view_name : el nombre de la vista se utiliza como destino de la relación. Para las clases de enrutadores estándar, será una string con el formato <nombre del modelo>-detalle.
- queryset : facilita las búsquedas de instancias de modelos al validar la entrada de campo. Las relaciones deben establecer explícitamente un conjunto de consultas o establecer read_only=True.
- many : para serializar más de una relación, debe establecer este argumento en True.
- allow_null : si se establece en Verdadero, el campo aceptará valores Ninguno o la string vacía para relaciones anulables. El valor predeterminado es falso.
- lookup_field : el campo en el destino se usa para la búsqueda. Corresponde a un argumento de palabra clave de URL en la vista a la que se hace referencia. El valor predeterminado es ‘pk’.
- lookup_url_kwarg : el nombre del argumento de palabra clave definido en la URL conf que corresponde al campo de búsqueda. De forma predeterminada, utiliza el mismo valor que lookup_field.
- formato : si se usan sufijos de formato, los campos con hipervínculos usarán el mismo sufijo de formato para el destino, a menos que se anule con el argumento de formato.
En nuestra relación inversa (Employee to EmployeeTask) hemos visto que, de forma predeterminada, el serializador (EmployeeSerializer) usa la clave principal para representar el objetivo de una relación (para incluir una relación inversa, debe agregarla explícitamente a la lista de campos). También hemos explorado otras representaciones como StringRelatedField y SlugRelatedField. Aquí, haremos uso de HyperlinkedRelatedField.
En la clase EmployeeSerializer, puede representar el campo de tareas como se muestra a continuación:
tasks = serializers.HyperlinkedRelatedField(many=True, read_only=True, view_name='employeetask-detail')
Puede reemplazar la clase EmployeeSerializer existente con la siguiente:
Python3
class EmployeeSerializer(serializers.HyperlinkedModelSerializer): url = serializers.HyperlinkedIdentityField( view_name='employee-detail', lookup_field='pk' ) tasks = serializers.HyperlinkedRelatedField(many=True, read_only=True, view_name='employeetask-detail') class Meta: model = Employee fields = ( 'url', 'pk', 'emp_id', 'name', 'gender', 'designation', 'tasks')
El comando HTTPie es:
http OBTENER :8000/empleados/8/
Producción
HTTP/1.1 200 OK Content-Length: 283 Content-Type: application/json Date: Fri, 22 Jan 2021 16:18:59 GMT Referrer-Policy: same-origin Server: WSGIServer/0.2 CPython/3.7.5 X-Content-Type-Options: nosniff X-Frame-Options: DENY { "designation": "Software Engineer", "emp_id": 128, "gender": "M", "name": "Mathew A", "pk": 8, "tasks": [ "http://localhost:8000/task/2/", "http://localhost:8000/task/1/", "http://localhost:8000/task/6/", "http://localhost:8000/task/7/" ], "url": "http://localhost:8000/employees/8/" }
Compartiendo la captura de pantalla del símbolo del sistema para su referencia
Si analizamos la salida, podemos notar que el campo de tareas muestra un conjunto o hipervínculos.
"tasks": [ "http://localhost:8000/task/2/", "http://localhost:8000/task/1/", "http://localhost:8000/task/6/", "http://localhost:8000/task/7/" ]
A continuación, comprendamos cómo se puede expresar la relación anidada mediante el uso de serializadores como campos.
Relación anidada
Una relación anidada hace posible incrustar la entidad referida. Si nos fijamos en el caso de EmployeeTask, se refiere al Empleado. Vamos a serializar EmployeeTask usando una relación anidada.
Puede usar el siguiente código para hacer referencia al campo de empleado en EmployeeTaskSerializer:
employee = EmployeeSerializer(read_only=True)
Puede reemplazar el EmployeeTaskSerializer con el siguiente código:
Python3
class EmployeeTaskSerializer(serializers.HyperlinkedModelSerializer): url = serializers.HyperlinkedIdentityField( view_name='employeetask-detail', lookup_field='pk' ) employee = EmployeeSerializer(read_only=True) class Meta: model = EmployeeTask fields = '__all__'
Recuperemos una entrada de EmployeeTask. El comando HTTPie es
http OBTENER :8000/tarea/1/
Producción
HTTP/1.1 200 OK Content-Length: 569 Content-Type: application/json Date: Fri, 22 Jan 2021 16:33:51 GMT Referrer-Policy: same-origin Server: WSGIServer/0.2 CPython/3.7.5 X-Content-Type-Options: nosniff X-Frame-Options: DENY { "created_date": "2021-01-21T09:42:39.792788Z", "deadline": "2021-01-25T00:00:00Z", "employee": { "designation": "Software Engineer", "emp_id": 128, "gender": "M", "name": "Mathew A", "pk": 8, "tasks": [ "http://localhost:8000/task/2/", "http://localhost:8000/task/1/", "http://localhost:8000/task/6/", "http://localhost:8000/task/7/" ], "url": "http://localhost:8000/employees/8/" }, "task_desc": "Write a Python program to interchange first and last element in a list", "task_name": "Interchange first and last elements in a list", "url": "http://localhost:8000/task/1/" }
Compartiendo la captura de pantalla del símbolo del sistema para su referencia
Puede notar que el campo de empleado muestra los detalles completos del empleado en lugar de solo la clave principal o el slug.
"employee": { "designation": "Software Engineer", "emp_id": 128, "gender": "M", "name": "Mathew A", "pk": 8, "tasks": [ "http://localhost:8000/task/2/", "http://localhost:8000/task/1/", "http://localhost:8000/task/6/", "http://localhost:8000/task/7/" ], "url": "http://localhost:8000/employees/8/" },
En esta sección, exploramos varios tipos de campos relacionales proporcionados por las relaciones del serializador DRF. Entendimos cómo cada campo relacional representa la relación con el objetivo. PrimaryKeyRelatedField representa el objetivo de la relación usando su clave principal, mientras que StringRelatedField usa el método __str__ del objetivo. En el caso de SlugRelatedField, representa el destino de la relación mediante un campo de destino. Finalmente, HyperlinkedIdentityField se usa como una relación de identidad, y HyperlinkedRealtedField representa el destino de la relación usando un hipervínculo.
Publicación traducida automáticamente
Artículo escrito por SonuGeorge y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA