image

Access unlimited bootcamps and 650+ courses

50
%OFF
Article image
Raissa Azevedo
Raissa Azevedo21/07/2023 00:19
Share

GUIA INTERMEDIÁRIO de Aplicação de API com Django Rest Framework

    "Simplifique o desenvolvimento de APIs no Django Rest Framework com um CRUD genérico, aprenda a personalizar ViewSets, lidar com relações e implementar paginação - tudo de forma clean e eficiente!"

    Para realizar esse passo a passo, é importante ter realizado o método básico antes... Se ainda não fez, clique aqui

    Criando CRUD genérico com Django Rest Framework:

    A melhoria de inserção de códigos é feita para evitar a repetição da estrutura no momento de adicionar as funções CRUD.

    Para substituir todas as funções criadas no views.py utiliza-se:

    from rest_framework import generics
    from .models import Curso, Avaliacao
    from .serializers import CursoSerializer, AvaliacaoSerializer
    
    class CursosAPIView(generics.ListCreateAPIView):
    queryset = Curso.objects.all()
    serializer_class = CursoSerializer
    
    class CursoAPIView(generics.RetrieveUpdateDestroyAPIView):
    queryset = Curso.objects.all()
    serializer_class = CursoSerializer
    

    Assim como no Django avançado existe o Class Based View o Django Rest também conta com melhorias de otimização de código.

    OBS: Repita o mesmo esquema para Avaliação

    O ListCreate indicado em genérico indica que é possível listar e criar os métodos, ou seja, as funções GET e POST já estão ativas.

    No queryset todos os objetos estão sendo passados, através do objects.all() e o serializer_class informa qual a classe vai sofrer serialização.

    image

    Agora além de manter o módulo raw de registro, também possui o formulário (HTML Form).

     

    Atualizando e Deletando os dados da API

    A única mudança na estrutura do código é a adição de RetrieveUpdateDestroyAPIView essa indicação na construção da classe ativa os elementos de CRUD de Update e Delete dos dados de uma API.

    class CursoAPIView(generics.RetrieveUpdateDestroyAPIView):
    queryset = Curso.objects.all()
    serializer_class = CursoSerializer
    

    OBS. O nome das classes de criação e de deleção precisa ser diferente também (sugestão: usar um no plural).

    Dessa forma, o arquivo de rotas (urls.py) também precisa ser atualizado.

    urlpatterns = [
    path('cursos/', CursosAPIView.as_view(), name='cursos'),
    path('cursos/<int:pk>/', CursoAPIView.as_view(), name='curso'),
    path('cursos/<int:curso_pk>/avaliacoes/', AvaliacoesAPIView.as_view(), name='curso_avaliacoes'),
    path('cursos/<int:curso_pk>/avaliacoes/<int:avaliacao_pk>/', AvaliacaoAPIView.as_view(), name='curso_avaliacao'),
    ]
    

    Na rota do elemento CRUD de deleção é adicionado o primary key, que é uma ID, através de <int:pk>.

    image

    Sobrescrevendo os métodos genéricos

    Trata-se de formas de sobrescrever os métodos para mudar o comportamento das funções da API.

    O objetivo é criar uma rota para associar duas APIs que são complementares… Ou seja, o curso e suas respectivas avaliações.

    urlpatterns = [
    path('cursos/', CursosAPIView.as_view(), name='cursos'),
    path('cursos/<int:pk>/', CursoAPIView.as_view(), name='curso'),
    path('cursos/<int:curso_pk>/avaliacoes/', AvaliacoesAPIView.as_view(), name='curso_avaliacoes'),
    path('cursos/<int:curso_pk>/avaliacoes/<int:avaliacao_pk>/', AvaliacaoAPIView.as_view(), name='curso_avaliacao'),
    path('avaliacoes/', AvaliacoesAPIView.as_view(), name='avaliacoes'),
    path('avaliacoes/<int:avaliacao_pk>/', AvaliacaoAPIView.as_view(), name='avaliacao')
    ]
    

    O elemento <int:curso_pk> indica que a ID extraída é do curso. Assim como, o elemento <int:avaliacao_pk> indica que a ID extraída é da avaliação.

    Dessa forma a url gerada vai numerar a ID do curso seguida da ID da avaliação.

    EX. api/v1/cursos/3/2  Isso significa que estamos observando a 2º avaliação do curso de ID 3.

    Com as rotas alteradas o arquivo views.py também precisa sofrer alterações:

    class AvaliacoesAPIView(generics.ListCreateAPIView):
    queryset = Avaliacao.objects.all()
    serializer_class = AvaliacaoSerializer
    
    def get_queryset(self):
      if self.kwargs.get('curso_pk'):
        return self.queryset.filter(curso_id=self.kwargs.get('curso_pk'))
      return self.queryset.all()
    

    O self.kwargs.get vai pegar os valores das pk (urls.py), e se tiver esse valor, retorna o queryset das avaliações filtradas para aquele curso. Caso não tenha, retorna todas as avaliações.

    Cursos representa uma coleção, mas a avaliação é individual. Portanto, a função para sobrescrever tem que ser o get_object() para tratar do objeto (avaliação) de forma individual.

    class AvaliacaoAPIView(generics.RetrieveUpdateDestroyAPIView):
    queryset = Avaliacao.objects.all()
    serializer_class = AvaliacaoSerializer
    
    def get_object(self):
      if self.kwargs.get('curso_pk'):
        return get_object_or_404(self.get_queryset(), curso_id=self.kwargs.get('curso_pk'), pk=self.kwargs.get('avaliacao_pk'))
      return get_object_or_404(self.get_queryset(), pk=self.kwargs.get('avaliacao_pk'))
    

    No tratamento do objeto individual a função get_object_or_404 vai buscar o objeto através do (‘curso_pk’) se positivo vai buscar as ID das avaliações. Ou automaticamente vai exibir o erro de 404 error caso não encontre ou haja erro de solicitação de dados.

    Utilizando ViewSets e Routers:

    O objetivo dos ViewSets e Router é diminuir a poluição visual dos endpoints, assim como facilitar na construção da estrutura da API.

    É muito utilizado nas melhorias e no versionamento das API, ou seja, manter a antiga funcionando e criar uma atualizada contendo melhorias que não estão presentes na versão anterior.

    OBS. Por isso a importância de indicar a versão (v1) na url de acesso da API.

     

    O ViewSets e Routers é uma melhoria que serve para automatizar a criação de endpoints nas API’s.

    O ViewSet consiste em agrupar toda a lógica de um determinado recurso em apenas uma classe,

     

    Contextualizando:

    from rest_framework import viewsets no arquivo views.py

    class CursoViewSet(viewsets.ModelViewSet):
    queryset = Curso.objects.all()
    serializer_class = CursoSerializer
    
    class AvaliacaoViewSet(viewsets.ModelViewSet):
    queryset = Avaliacao.objects.all()
    serializer_class = AvaliacaoSerializer
    

    Essa estrutura de dados faz a mesma coisa que aquela sequencia de dados separadas de curso e avaliação construídas no CRUD anteriormente.

     

    No arquivo url.py da aplicação cursos:

    from rest_framework.routers import SimpleRouter

    from django.urls import path
    from rest_framework.routers import SimpleRouter
    
    from .views import (
    CursoAPIView,
    CursosAPIView,
    AvaliacaoAPIView,
    AvaliacoesAPIView,
    CursoViewSet,
    AvaliacaoViewSet)
    
    router = SimpleRouter()
    router.register('cursos', CursoViewSet)
    router.register('avaliacoes', AvaliacaoViewSet)
    

    Note que a todo momento você está modificando o arquivo urls.py da sua aplicação... Agora...

    No arquivo urls.py do projeto:

    from django.contrib import admin
    from django.urls import path, include
    
    from cursos.urls import router
    
    urlpatterns = [
    path('api/v1/', include('cursos.urls')),
    path('api/v2/', include(router.urls)),
    path('admin/', admin.site.urls),
    path('auth/', include('rest_framework.urls')),
    ]
    

    Ou seja, não há necessidade de construção manual das rotas. O router cria essas rotas de forma automatizada.

    OBS: Entretanto usando esse método a rota conjunta não irá funcionar. Porque o SimpleRouter só gera o CRUD para um único model.

    Até esse ponto você já utilizou 3 métodos de aplicação de API com Django... O Básico, o CRUD e o Simple Router :)

    Até breve!

    Share
    Comments (0)