Práctica UT05 Servicios Web
2/4/28Alrededor de 2 min
Práctica 5: Gestión de Socios con Validación Externa
Apartado 1: Crear endpoint validador de DNI
Objetivo
Convertir una función Python existente en un endpoint funcional de la API REST.
Código de la función
# socios/dni_utils.py
import re
def check_dni(dni: str) -> dict:
"""
Valida el formato de un DNI español (8 dígitos + letra).
Args:
dni: Cadena con el documento a validar
Returns:
dict con el resultado de la validación
"""
dni = dni.upper().strip()
# Patrón: 8 dígitos seguidos de letra válida
if not re.match(r'^\d{8}[A-HJ-NP-TV-Z]$', dni):
return {
"valido": False,
"documento": dni,
"error": "Formato inválido. Use: 12345678A"
}
# Validar letra (algoritmo módulo 23)
numero = int(dni[:-1])
letra = dni[-1]
letras_validas = 'TRWAGMYFPDXBNJZSQVHLCKE'
if letras_validas[numero % 23] != letra:
return {
"valido": False,
"documento": dni,
"error": "Letra incorrecta"
}
return {
"valido": True,
"documento": dni,
"tipo": "DNI"
}Tareas a realizar
- Crear el archivo
dni_utils.pycon la función proporcionada - Crear un endpoint POST en
api_views.pyaccesible en/api/socios/check-dni/ - El endpoint debe:
- Recibir JSON:
{"documento": "12345678A"} - Usar la función
check_dni()para validar - Devolver el resultado como JSON
- Recibir JSON:
Guía de ayuda con referencias
| Problema | Referencias a consultar |
|---|---|
| ¿Cómo crear un endpoint que no use modelo (solo recibe datos y devuelve resultado)? | Buscar: APIView drf, GenericAPIView, o @action en ViewSet |
| ¿Cómo acceder a los datos del body de la petición POST? | Buscar: request.data drf, django rest framework request object |
| ¿Cómo importar y usar una función desde otro archivo? | Buscar: python import from module |
| ¿Cómo devolver una respuesta JSON con código HTTP 200 o 400 según validez? | Buscar: Response drf status code, rest_framework.response |
Criterios de aceptación
Apartado 2: Extender el Serializador
Objetivo
Usar la misma lógica de validación pero integrada en el flujo de creación de socios.
Tareas a realizar
Crear
DNIValidatorSerializerenserializers.py:- Campo
documentode tipo CharField - Método
validate_documento()que use la funcióncheck_dni() - Si
check_dni()devuelvevalido: False, lanzarValidationError
- Campo
Modificar
SocioCreateSerializer:- Usar
DNIValidatorSerializercomo base o llamar a su validación - Asegurar que no se puede crear un socio con DNI inválido
- Usar
Guía de ayuda con referencias
| Problema | Referencias |
|---|---|
| ¿Cómo validar un campo específico en un serializer? | Buscar: validate_<field> drf, field level validation |
| ¿Cómo reutilizar validación entre serializers? | Buscar: serializer inheritance drf, mixin pattern |
¿Cómo convertir el dict de check_dni() en excepción de validación? | Buscar: serializers.ValidationError, raise validation error drf |
Criterios de aceptación
PDF entregable:
En la entrega de la tarea se deben incluir (a tamaño de letra legible!!!)
Capturas de pantalla de:
- POST
/api/socios/check-dni/con DNI válido (200 OK) - POST
/api/socios/check-dni/con DNI inválido (400 Bad Request) - POST
/api/socios/creando socio con DNI inválido (error de validación)
- POST
Código de:
dni_utils.py(proporcionado, sin cambios)api_views.pycon el endpointserializers.pycon la validación integrada
Breve explicación (5-10 líneas) de qué problema tuviste al montar el endpoint y cómo lo resolviste
Ejemplos de uso esperados
Endpoint check-dni (Parte 1)
# Válido
curl -X POST http://localhost:8000/api/socios/check-dni/ \
-H "Content-Type: application/json" \
-d '{"documento": "12345678A"}'Respuesta 200:
{"valido": true, "documento": "12345678A", "tipo": "DNI"}# Inválido
curl -X POST http://localhost:8000/api/socios/check-dni/ \
-H "Content-Type: application/json" \
-d '{"documento": "12345678Z"}'Respuesta 400:
{"valido": false, "documento": "12345678Z", "error": "Letra incorrecta"}Creación de socio (Parte 2)
curl -X POST http://localhost:8000/api/socios/ \
-H "Content-Type: application/json" \
-d '{"nombre": "Ana", "apellidos": "García", "documento_identidad": "12345678Z", ...}'Respuesta 400:
{"documento_identidad": ["Letra incorrecta"]}