Este artigo explora os pilares da construção de APIs web com Django REST framework (DRF), abordando desde os padrões de arquitetura até a implementação prática.
- Padrões de Aplicações Web
No desenvolvimento web, encontramos duas abordagens principais:
-
Frontend e Backend Acoplados: Onde o servidor renderiza o HTML e o envia diretamente para o cliente.
-
Frontend e Backend Separados: Uma arquitetura moderna onde o frontend (geralmente em JavaScript) consome dados de uma API fornecida pelo backend.
-
Interfaces de API
Para garantir consistência e reduzir custos de colaboração em equipes, é crucial adotar um padrão para a criação de interfaces de API. As abordagens mais comuns são RPC e RESTful.
- RPC (Remote Procedure Call): Traduzido como Chamada de Procedimento Remoto, envolve a invocação de funções ou métodos em um servidor remoto. Um exemplo seria
http://www.example.com/api?action=getAllStudents¶ms=301&sex=1, onde a funçãogetAllStudentsé chamada com parâmetros específicos. Essa abordagem pode levar a um grande número de endpoints e dificuldade em encontrar as APIs corretas. - RESTful: Significa Transferência de Estado Representacional. Essa abordagem trata todos os dados e arquivos no backend como recursos. As interações com esses recursos são feitas através de verbos HTTP (GET, POST, PUT, DELETE) em URLs que representam os próprios recursos.
- Especificação RESTful API
REST (Representational State Transfer) é um estilo arquitetural para projetar APIs web, popularizado por Roy Fielding. A filosofia RESTful considera que o backend fornece acesso a recursos de dados. A URL define o recurso a ser manipulado, e os métodos HTTP indicam a operação a ser realizada (criação, leitura, atualização, exclusão - CRUD).
| Método HTTP | URL | Operação no Backend |
|---|---|---|
| GET | /students |
Obter todos os estudantes |
| POST | /students |
Criar um novo estudante |
| GET | /students/<pk> |
Obter um estudante específico pelo seu ID |
| PUT | /students/<pk> |
Atualizar um estudante específico pelo seu ID |
| DELETE | /students/<pk> |
Excluir um estudante específico pelo seu ID |
Qualquer framework web pode ser utilizado para implementar APIs que sigam as especificações RESTful.
- Serialização
A serialização é um processo central no desenvolvimento de APIs, envolvendo a conversão de formatos de dados.
- Serialização: Converte dados compreensíveis para humanos (como objetos do Django ORM) em formatos utilizáveis por outros sistemas (como JSON ou XML), tornando-os prontos para serem enviados ao cliente.
- Desserialização: Converte dados recebidos de fontes externas (como JSON do frontend) em formatos que o backend possa entender e processar (como objetos de modelo do Django), permitindo, por exemplo, salvar dados no banco de dados.
- Django REST framework (DRF)
O Django REST framework é uma poderosa e flexível ferramenta construída sobre o Django, projetada para simplificar o desenvolvimento de APIs RESTful. Ele oferece:
- Serializadores (Serializers): Facilita a conversão entre objetos de modelo e formatos de dados como JSON.
- Visualizações Baseadas em Classes (Class-Based Views) e ViewSets: Reduzem a verbosidade na escrita de lógicas de visualização.
- Autenticação e Permissões: Suporte robusto para controle de acesso.
- Limitação de Taxa (Throttling): Protege a API contra uso excessivo.
- Filtragem, Paginação e Ordenação: Funcionalidades esssenciais para lidar com grandes volumes de dados.
- Interface Web Interativa: Uma interface visual para testar e explorar APIs.
Principais Vantagens:
- Simplifica a criação de serializadores e desserializadores.
- Oferece diversas abordagens para construir visualizações (views).
- Suporta múltiplos métodos de autenticação.
- Inclui recursos integrados para gerenciamento de tráfego da API.
- Proporciona uma interface amigável para testes.
- Instalação e Configuração do Ambiente
O DRF possui os seguintes requisitos:
- Python (versões 2.7, 3.2+)
- Django (versões 1.10+)
Como o DRF é um aplicativo Django, ele pode ser adicionado a um projeto Django existente.
6.1. Instalação do DRF
Certifique-se de ter o Django instalado e preferencialmente em um ambiente virtual.
pip install djangorestframework
6.1.1. Criação de um Projeto Django
Use o comando do Django para iniciar um novo projeto:
django-admin startproject meu_projeto_drf
Configure o interpretador Python e o ambiente virtual no seu IDE (como o PyCharm).
6.2. Adição do App rest_framework
No arquivo settings.py do seu projeto, adicione 'rest_framework' à lista INSTALLED_APPS:
INSTALLED_APPS = [
# ... outros apps
'rest_framework',
'nome_do_seu_app', # Ex: 'students'
]
6.3. Experiência Rápida com DRF
A seguir, um exemplo simplificado de como o DRF pode agilizar o desenvolvimento de uma API CRUD para um modelo.
6.3.1. Criação de um Modelo
Defina um modelo para representar seus dados.
# students/models.py
from django.db import models
class Student(models.Model):
nome = models.CharField(max_length=100, verbose_name="Nome")
sexo = models.BooleanField(default=True, verbose_name="Sexo")
idade = models.IntegerField(verbose_name="Idade")
codigo_turma = models.CharField(max_length=5, verbose_name="Código da Turma")
descricao = models.TextField(verbose_name="Assinatura Pessoal")
class Meta:
db_table = "tb_student"
verbose_name = "Estudante"
verbose_name_plural = verbose_name
def __str__(self):
return self.nome
Para usar MySQL, instale o driver:
pip install PyMySQL
Configure o settings.py para usar MySQL e instale o driver no __init__.py do projeto principal.
6.3.1.1. Migração de Dados
Execute os comandos para criar as tabelas no banco de dados:
python manage.py makemigrations
python manage.py migrate
6.3.2. Criação do Serializador
Defina um serializador para o modelo Student.
# students/serializers.py
from rest_framework import serializers
from .models import Student
class StudentModelSerializer(serializers.ModelSerializer):
class Meta:
model = Student
fields = "__all__"
6.3.3. Criação da Visualização (View)
Utilize um ModelViewSet para simplificar a lógica CRUD.
# students/views.py
from rest_framework.viewsets import ModelViewSet
from .models import Student
from .serializers import StudentModelSerializer
class StudentViewSet(ModelViewSet):
queryset = Student.objects.all()
serializer_class = StudentModelSerializer
6.3.4. Definição das Rotas (URLs)
Configure as URLs para o seu ViewSet.
# students/urls.py
from rest_framework.routers import DefaultRouter
from .views import StudentViewSet
router = DefaultRouter()
router.register(r'students', StudentViewSet, basename='student')
urlpatterns = router.urls
# project/urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include('students.urls')), # Exemplo de prefixo 'api/'
]
6.3.5. Teste da API
Execute o servidor de desenvolvimento:
python manage.py runserver
Acesse a URL base da sua API (ex: http://127.0.0.1:8000/api/students/) no navegador. O DRF fornecerá uma interface interativa para visualizar e testar os endpoints de listagem, criação, recuperação, atualização e exclusão de estudantes.
- Serializador - Serializer
Os serializadores no DRF são responsáveis por:
- Serialização: Converter objetos do modelo em formatos como dicionários, que podem ser posteriormente convertidos em JSON para a resposta da API.
- Desserialização: Converter dados recebidos (como JSON) em dicionários e, opcionalmente, em objetos de modelo.
- Validação de Dados: Garantir que os dados recebidos estejam corretos e formatados adequadamente antes de serem processados.
7.1. Definição de um Serializador
Um serializador é definido como uma classe que herda de serializers.Serializer ou serializers.ModelSerializer.
# sers/serializers.py
from rest_framework import serializers
from students.models import Student
class StudentSerializer(serializers.Serializer):
id = serializers.IntegerField(read_only=True)
nome = serializers.CharField(max_length=100)
idade = serializers.IntegerField(min_value=0, max_value=150)
sexo = serializers.BooleanField()
descricao = serializers.CharField(allow_blank=True, required=False)
# Validações personalizadas podem ser adicionadas aqui (validate_field, validate)
def create(self, validated_data):
return Student.objects.create(**validated_data)
def update(self, instance, validated_data):
instance.nome = validated_data.get('nome', instance.nome)
instance.idade = validated_data.get('idade', instance.idade)
instance.sexo = validated_data.get('sexo', instance.sexo)
instance.descricao = validated_data.get('descricao', instance.descricao)
instance.save()
return instance
7.2. Criação de um Objeto Serializador
Serializadores são instanciados passando os dados ou o objeto a ser processado:
- Para serialização:
serializer = StudentSerializer(instance=objeto_estudante) - Para desserialização:
serializer = StudentSerializer(data=dados_recebidos) - O parâmetro
contextpode ser usado para passar informações adicionais, como o objetorequest.
7.3. Uso do Serializador
7.3.1. Serialização
Converter um objeto de modelo em um formato serializável.
# Em uma view (ex: sers/views.py)
from django.http import JsonResponse
from django.views import View
from students.models import Student
from .serializers import StudentSerializer
class SerializeStudentView(View):
def get(self, request, pk):
try:
student = Student.objects.get(pk=pk)
serializer = StudentSerializer(instance=student)
return JsonResponse(serializer.data)
except Student.DoesNotExist:
return JsonResponse({'error': 'Estudante não encontrado'}, status=404)
class ListStudentsView(View):
def get(self, request):
students = Student.objects.all()
# Para serializar múltiplos objetos, use many=True
serializer = StudentSerializer(instance=students, many=True)
return JsonResponse(serializer.data, safe=False) # safe=False para listas
- Serializador - Serializer (Continuação)
8.3.2. Desserialização
Converter dados recebidos em objetos ou estruturas compreensíveis, incluindo validação.
8.3.2.1. Validação de Dados
O método is_valid() é crucial para validar os dados. Ele retorna True se os dados forem válidos e False caso contrário. Os erros são acessíveis via serializer.errors e os dados validados via serializer.validated_data.
# Em uma view (ex: unsers/views.py)
from django.http import JsonResponse
from django.views import View
from .serializers import StudentSerializer # Assumindo que StudentSerializer foi definido para validação
from students.models import Student
class CreateStudentView(View):
def post(self, request):
data = request.POST # Ou request.data para APIs baseadas em JSON
serializer = StudentSerializer(data=data)
if serializer.is_valid():
# Os dados validados estão em serializer.validated_data
# Para salvar, você pode chamar serializer.save() se os métodos create/update foram definidos
student = serializer.save()
return JsonResponse({'message': 'Estudante criado com sucesso', 'id': student.id})
else:
# Retorna os erros de validação
return JsonResponse(serializer.errors, status=400)
Métodos de Validação Personalizada:
validate_<field_name>(self, value): Valida um campo específico.validate(self, data): Valida múltiplos campos em conjunto.validators(parâmetro do campo): Uma lista de funções ou classes de validação reutilizáveis.
# Exemplo de validação personalizada em StudentSerializer
class StudentSerializer(serializers.Serializer):
# ... campos ...
nome = serializers.CharField(max_length=20, required=True)
idade = serializers.IntegerField(min_value=0, required=True)
def validate_nome(self, value):
if value == "Admin":
raise serializers.ValidationError("Nome de usuário inválido.")
return value
def validate(self, data):
if data.get('idade', 0) < 18 and data.get('nome') == "Estudante Menor":
raise serializers.ValidationError("Estudantes menores requerem um nome específico.")
return data
8.3.2.2. Desserialização e Salvamento de Dados
Após a validação bem-sucedida, serializer.save() chama os métodos create() ou update() definidos no serializador para persistir os dados.
8.3.3. Serializador de Modelo (ModelSerializer)
ModelSerializer é uma classe de serializador que abstrai a criação de campos com base em um modelo Django.
# msers/serializers.py
from rest_framework import serializers
from students.models import Student
class StudentModelSerializer(serializers.ModelSerializer):
class Meta:
model = Student
fields = ['id', 'nome', 'idade', 'sexo', 'descricao'] # Ou '__all__' ou exclude
read_only_fields = ['id'] # Campo apenas para leitura na serialização
extra_kwargs = {
'sexo': {'write_only': True}, # Campo apenas para escrita na desserialização
'descricao': {'allow_blank': True, 'required': False}
}
ModelSerializer simplifica a definição de campos, validações e a implementação dos métodos create e update, tornando o código mais conciso.