Article image
Raissa Azevedo
Raissa Azevedo21/07/2023 00:19
Compartilhe

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

  • #PostgreSQL
  • #Django
  • #Python

"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!

Compartilhe
Comentários (0)