Vistas basadas en clases
Modelo Cliente
También podemos escribir nuestras vistas de API utilizando vistas basadas en clases, en lugar de vistas basadas en funciones. Como veremos, este es un patrón poderoso que nos permite reutilizar la funcionalidad común y nos ayuda a mantener nuestro código Limpio.
Uso de vistas genéricas basadas en clases
En el archivo Apps/clientes/views.py
colocamos el código correspondiente para realizar el CRUD completo.
from django.shortcuts import render
from django.http import Http404
from rest_framework.response import Response
from rest_framework import generics
from rest_framework import status
from Apps.clientes.models import Cliente
from Apps.clientes.serializers import ClienteSerializer
# Create your views here.
class ClienteList(generics.ListCreateAPIView):
"""
Lista de Clientes
"""
queryset = Cliente.objects.all()
serializer_class = ClienteSerializer
class ClienteDetail(generics.RetrieveUpdateDestroyAPIView):
"""
Retrieve, update or delete de los clientes por pk
"""
queryset = Cliente.objects.all()
serializer_class = ClienteSerializer
Código en el archivo Apps/clientes/serializers.py
from dataclasses import field
from statistics import mode
from rest_framework import serializers
from Apps.clientes.models import Cliente
class ClienteSerializer(serializers.ModelSerializer):
# len_nombreCliente = serializers.SerializerMethodField()
class Meta:
model = Cliente
fields = "__all__"
# exclude = ['passwordCliente']
# fields = (
# 'pk',
# 'nombreCliente',
# 'direccionCliente',
# 'telefonoCliente',
# 'correoCliente',
# 'passwordCliente',
# )
# def get_len_nombreCliente(self, object):
# length = len(object.nombreCliente)
# return length
# def validate(self, data):
# if data['nombreCliente'] == data['direccionCliente']:
# raise serializers.ValidationError('Nombre y Correo No pueden ser iguales')
# else:
# return data
def validate_nombreCliente(self, value):
if len(value) < 3:
raise serializers.ValidationError('Nombre no puede ser tan corto')
else:
return value
def validate_passwordCliente(self, value):
if len(value) < 8:
raise serializers.ValidationError('El Password debe tener mayor de 8 caracteres')
else:
return value
Código en el archivo Apps/clientes/urls.py
from django.urls import path
from Apps.clientes.views import ClienteList, ClienteDetail
app_name = "clientes"
urlpatterns = [
path('', ClienteList.as_view()),
path('<int:pk>', ClienteDetail.as_view()),
Uso de Mezclas de clases
Una de las grandes ventajas de usar vistas basadas en clases es que nos permite componer fácilmente fragmentos de comportamiento reutilizables.
Las operaciones de creación/recuperación/actualización/eliminación que hemos estado usando hasta ahora serán bastante similares para cualquier vista de API respaldada por modelo que creemos. Esos bits de comportamiento común se implementan en las clases mixtas del marco REST.
Echemos un vistazo a cómo podemos componer las vistas usando las clases mixin. Aquí está nuestro Apps/clientes/views.py
from django.shortcuts import render
from django.http import Http404
from rest_framework.response import Response
from rest_framework import generics
from rest_framework import mixins
from rest_framework import status
from Apps.clientes.models import Cliente
from Apps.clientes.serializers import ClienteSerializer
# Create your views here.
class ClienteList(mixins.ListModelMixin,
mixins.CreateModelMixin,
generics.GenericAPIView):
"""
Lista de Clientes
"""
queryset = Cliente.objects.all()
serializer_class = ClienteSerializer
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 ClienteDetail(mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
generics.GenericAPIView):
"""
Retrieve, update or delete de los clientes por pk
"""
queryset = Cliente.objects.all()
serializer_class = ClienteSerializer
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 delete(self, request, *args, **kwargs):
return self.destroy(request, *args, **kwargs)
Los archivos:
Apps/clientes/serializers.py
Apps/clientes/urls.py
Quedan exactamente igual al método anterior.
Reescribiendo nuestra API usando vistas basadas en clases
En el archivo Apps/clientes/views.py
colocamos el código correspondiente para realizar el CRUD completo.
from django.shortcuts import render
from django.http import Http404
from django.http import JsonResponse
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework import status
from Apps.clientes.models import Cliente
from Apps.clientes.serializers import ClienteSerializer, ClienteListSerializer
# Create your views here.
class ClienteList(APIView):
"""
Lista de Clientes
"""
def get(self, request, format=None):
clientes = Cliente.objects.all()
# data = {"results": list(clientes.values("nombreCliente", "direccionCliente", "telefonoCliente", "correoCliente", "passwordCliente"))}
# print(data)
# return JsonResponse(data)
serializer = ClienteListSerializer(clientes, many=True)
return Response({"clientes":serializer.data})
def post(self, request, format=None):
serializer = ClienteSerializer(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 ClienteDetail(APIView):
"""
Retrieve, update or delete de los clientes por pk
"""
def get_object(self, pk):
# Returns an object instance that should
# be used for detail views.
try:
return Cliente.objects.get(pk=pk)
except Cliente.DoesNotExist:
raise Http404
def get(self, request, pk, format=None):
cliente = self.get_object(pk)
serializer = ClienteListSerializer(cliente)
return Response({"cliente":serializer.data})
def put(self, request, pk, format=None):
cliente = self.get_object(pk)
serializer = ClienteSerializer(cliente, 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):
cliente = self.get_object(pk)
serializer = ClienteSerializer(cliente,
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):
cliente = self.get_object(pk)
cliente.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
Los archivos:
Apps/clientes/serializers.py
Apps/clientes/urls.py
Quedan exactamente igual al método anterior.
Ahora probamos con http://localhost:8000/clientes/
También podemos probar el método Post,
Donde se muestra luego el resultado, con el método Get.
Ahora probamos el Método Put.
Se obtiene como resultado
Y por ultimo probamos el Metodo Delete
Validaciones de los Atributos
Las validaciones de cada uno de los atributos se hacen en Apps/clientes/serializers.py
from dataclasses import field
from statistics import mode
from rest_framework import serializers
from Apps.clientes.models import Cliente
class ClienteSerializer(serializers.ModelSerializer):
class Meta:
model = Cliente
# fields = "__all__"
exclude = ['passwordCliente']
# fields = (
# 'pk',
# 'nombreCliente',
# 'direccionCliente',
# 'telefonoCliente',
# 'correoCliente',
# 'passwordCliente',
# )
def validate(self, data):
if data['nombreCliente'] == data['direccionCliente']:
raise serializers.ValidationError('Nombre y Correo No pueden ser iguales')
else:
return data
def validate_nombreCliente(self, value):
if len(value) < 3:
raise serializers.ValidationError('Nombre no puede ser tan corto')
else:
return value
Personalizacion de los Atributos
Las personalizaciones de nuevos atributos se hacen en Apps/clientes/serializers.py
from dataclasses import field
from statistics import mode
from rest_framework import serializers
from Apps.clientes.models import Cliente
class ClienteSerializer(serializers.ModelSerializer):
len_nombreCliente = serializers.SerializerMethodField()
class Meta:
model = Cliente
# fields = "__all__"
exclude = ['passwordCliente']
# fields = (
# 'pk',
# 'nombreCliente',
# 'direccionCliente',
# 'telefonoCliente',
# 'correoCliente',
# 'passwordCliente',
# )
def get_len_nombreCliente(self, object):
length = len(object.nombreCliente)
return length
def validate(self, data):
if data['nombreCliente'] == data['direccionCliente']:
raise serializers.ValidationError('Nombre y Correo No pueden ser iguales')
else:
return data
def validate_nombreCliente(self, value):
if len(value) < 3:
raise serializers.ValidationError('Nombre no puede ser tan corto')
else:
return value
Envolviendo Vistas en API - Con @apiview
En el archivo Apps/clientes/views.py
colocamos el código correspondiente para realizar el CRUD completo.
from django.shortcuts import render
from django.http import Http404
from rest_framework.response import Response
from rest_framework.decorators import api_view
from rest_framework import status
from Apps.clientes.models import Cliente
from Apps.clientes.serializers import ClienteSerializer
# Create your views here.
@api_view(['GET', 'POST'])
def cliente_list(request):
"""
List all code snippets, or create a new snippet.
"""
if request.method == 'GET':
clientes = Cliente.objects.all()
serializer = ClienteSerializer(clientes, many=True)
return Response(serializer.data)
elif request.method == 'POST':
serializer = ClienteSerializer(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', 'DELETE'])
def cliente_detail(request, pk):
"""
Retrieve, update or delete a code snippet.
"""
try:
cliente = Cliente.objects.get(pk=pk)
except Cliente.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)
if request.method == 'GET':
serializer = ClienteSerializer(cliente)
return Response(serializer.data)
elif request.method == 'PUT':
serializer = ClienteSerializer(cliente, 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 == 'DELETE':
cliente.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
Código en el archivo Apps/clientes/urls.py
"""
Envolviendo Vistas de Api
"""
from django.urls import path
from Apps.clientes.views import cliente_list, cliente_detail
urlpatterns = [
path('', cliente_list),
path('<int:pk>/', cliente_detail),
]
El archivo:
Apps/clientes/serializers.py
Quedan exactamente igual al método anterior.