Entendeno Serializers no Django: A Ponte Entre Seus Modelos e a API Moderna Parte 3
- Published on
- Published on
- /4 mins read/---
Tutorial 3: Views Baseadas em Classes - Django REST Framework
Também podemos escrever nossas views de API usando views baseadas em classes, em vez de views baseadas em funções. Como veremos, este é um padrão poderoso que nos permite reutilizar funcionalidades comuns e nos ajuda a manter nosso código DRY (Don't Repeat Yourself - Não se Repita).
Reescrevendo Nossa API Usando Views Baseadas em Classes
Começaremos reescrevendo a view raiz como uma view baseada em classe. Tudo o que isso envolve é uma pequena refatoração de views.py
.
from snippets.models import Snippet
from snippets.serializers import SnippetSerializer
from django.http import Http404
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
class SnippetList(APIView):
"""
Lista todos os snippets ou cria um novo snippet.
"""
def get(self, request, format=None):
snippets = Snippet.objects.all()
serializer = SnippetSerializer(snippets, many=True)
return Response(serializer.data)
def post(self, request, format=None):
serializer = SnippetSerializer(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)
Até agora, tudo bem. Parece muito semelhante ao caso anterior, mas temos uma melhor separação entre os diferentes métodos HTTP. Também precisaremos atualizar a view da instância em views.py
.
class SnippetDetail(APIView):
"""
Recupera, atualiza ou exclui uma instância de snippet.
"""
def get_object(self, pk):
try:
return Snippet.objects.get(pk=pk)
except Snippet.DoesNotExist:
raise Http404
def get(self, request, pk, format=None):
snippet = self.get_object(pk)
serializer = SnippetSerializer(snippet)
return Response(serializer.data)
def put(self, request, pk, format=None):
snippet = self.get_object(pk)
serializer = SnippetSerializer(snippet, data=request.data)
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):
snippet = self.get_object(pk)
snippet.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
Está ficando bom. Novamente, ainda é muito semelhante à view baseada em função no momento.
Também precisaremos refatorar nosso snippets/urls.py
ligeiramente agora que estamos usando views baseadas em classes.
from django.urls import path
from rest_framework.urlpatterns import format_suffix_patterns
from snippets import views
urlpatterns = [
path('snippets/', views.SnippetList.as_view()),
path('snippets/<int:pk>/', views.SnippetDetail.as_view()),
]
urlpatterns = format_suffix_patterns(urlpatterns)
Ok, terminamos. Se você executar o servidor de desenvolvimento, tudo deverá funcionar como antes.
Usando Mixins
Uma das grandes vantagens de usar views baseadas em classes é que isso nos permite compor facilmente pedaços de comportamento reutilizáveis.
As operações de criação/recuperação/atualização/exclusão que usamos até agora serão bastante semelhantes para quaisquer views de API baseadas em modelo que criarmos. Esses pedaços de comportamento comum são implementados nas classes mixin do REST framework.
Vamos dar uma olhada em como podemos compor as views usando as classes mixin. Aqui está nosso módulo views.py
novamente.
from snippets.models import Snippet
from snippets.serializers import SnippetSerializer
from rest_framework import mixins
from rest_framework import generics
class SnippetList(mixins.ListModelMixin,
mixins.CreateModelMixin,
generics.GenericAPIView):
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs)
Vamos parar um momento para examinar exatamente o que está acontecendo aqui. Estamos construindo nossa view usando GenericAPIView
e adicionando ListModelMixin
e CreateModelMixin
.
A classe base fornece a funcionalidade principal, e as classes mixin fornecem as ações .list()
e .create()
. Em seguida, estamos vinculando explicitamente os métodos get
e post
às ações apropriadas. Coisas simples o suficiente até agora.
class SnippetDetail(mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
generics.GenericAPIView):
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
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)
Muito semelhante. Novamente, estamos usando a classe GenericAPIView
para fornecer a funcionalidade principal e adicionando mixins para fornecer as ações .retrieve()
, .update()
e .destroy()
.
Usando Views Genéricas Baseadas em Classes
Usando as classes mixin, reescrevemos as views para usar um pouco menos de código do que antes, mas podemos ir um passo além. O REST framework fornece um conjunto de views genéricas já combinadas que podemos usar para reduzir ainda mais nosso módulo views.py
.
from snippets.models import Snippet
from snippets.serializers import SnippetSerializer
from rest_framework import generics
class SnippetList(generics.ListCreateAPIView):
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
class SnippetDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
Uau, isso é muito conciso. Obtivemos uma grande quantidade de graça, e nosso código parece um Django bom, limpo e idiomático.
Em seguida, passaremos para a parte 4 (substitua pelo link real) do tutorial, onde veremos como podemos lidar com autenticação e permissões para nossa API.