Olá, esse é um tutorial sobre Django Rest Framework, preparado para o Curso de Verão de Django Rest Framework e ReactNative, promovidos por Grupy-RN, Natal JS com apoio da B2SOFT.
Os modelos aqui utilizados são baseados no tutorial de Django do Django Girls.
O que será abordado por aqui?
- O que é API e REST
- Verbos HTTP
- O que é Django Rest Framework
- Modelo de dados
- Serializers
- Views baseadas em função
- Views baseadas em classe
- Autenticação e Permissões
- Baseada em Token
- Routers
- Consumindo a API
- Curl (Usar Postman)
API é um acrônimo do inglês application programming interface, ou interface de programação de aplicações em português.
Em linhas gerais, uma API é um ponto de acesso de uma certa aplicação X, para que outras aplicações Y, W e Z consigam acessar funcionalidades desta, sem necessariamente conhecer detalhes da implementação da aplicação ou acessar diretamente seus servidores, etc.
Resumidamente, APIs permitem de forma rápida, prática e segura (ou pelo menos deveriam permitir) a comunicação entre aplicações.
Certo, então o que é uma API Rest?
Bem, tudo começa com uma sigla que provavelmente você já viu: HTTP. Este é o principal protocolo de comunicação entre sistemas web usado no mundo, que já existe a mais de 20 anos.
O HTTP trata de resolver requisições entre aplicações, para isso existem alguns verbos HTTP, entre eles estão GET, POST, DELETE, mas existem diversos outros, e eles existem pra facilitar o entendimento de nós humanos sobre o que está ocorrendo na web. É simples perceber que uma requisição de GET tem como objetivo "pegar" informações, enquanto DELETE visa apagar algo (sempre tenham cuidado com o delete).
Esses princípios são o que definem o REST, que significa Representational State Transfer, ou em português, Transferência de Estado Representacional (isso nâo é tâo complicado quanto parece). Em resumo, é uma abstração da arquitetura web, e esses princípios, padrões e regras (que iremos aprender), quando seguidos permitem a criação de um sistema ou projeto, no nosso caso uma API com interfaces bem definidas, o que facilita sua comunicação com outras aplicações.
** O framework Django REST é um kit de ferramentas poderoso e flexível para criar APIs da Web. ** (Tradução do google da definição do próprio site do DRF).
O django rest framework é uma biblioteca python que se acopla em projetos django, e entregam uma super base para construção de APIs REST, com toda a robustez do Django, altamente extensível e confiável.
Além disso, o django rest framework é tão simples de instalar em usar como qualquer pacote python.
Considerando que você já tem o pip instalado (afinal, você deve ter feito o tutorial do Django girls né?!), e já ativou sua virtualenv, basta UM ÚNICO COMANDO.
Se você nao lembra, para ativar virtualenv, basta este comando:
$ source venv/bin/activate
Para instalar o django rest framework use este comando:
$ pip install djangorestframework
O legal é que caso você ainda não tenha o django instalado, ao instalar o djangorestframework ele automaticamente também instala o django!
Como estamos dando continuidade ao tutorial do django girls, não vamos iniciar um novo projeto, apenas adicionaremos o djangorestframework nas configurações do projeto no arquivo settings.py localizado na pasta mysite.
INSTALLED_APPS = [
...,
'rest_framework',
]
Pronto! Já temos o Django rest framework em nosso projeto!
TODO
Os Serializadores do DRF permitem que dados "complexos", como objetos e querysets sejam convertidos em tipos de dados Python, para assim serem renderizados em formato JSON (ou outros formatos como xml, yml, etc.) e assim permite que a comunicação entre as aplicações ocorra de forma correta, que é o objetivo de uma API.
Para quem já conhece, os serializadores do DRF parecem muito com os Form e ModelForm do Django.
No caso da nossa aplicação, usaremos o ModelSerializer
, que é um serializador completo pré-pronto, com operações padrão, para instanciações e consultas de nossos modelos.
No nosso caso, faremos um serializador para o modelo Post, o exemplo veremos abaixo:
Crie um arquivo serializers.py dentro da pasta blog:
from rest_framework import serializers
from .models import Post
class PostModelSerializer(serializers.ModelSerializer):
class Meta:
model = Post
fields = ('author', 'title', 'text')
Como nós usamos um ModelSerializer, precisamos definir uma classe Meta (responsável por configurar o serializer), onde diremos ao DRF sobre qual modelo aquele serializador irá atuar, bem como quais atributos, fields, ele irá serializar.
Neste tipo é necessário implementar tudo do zero. Neste tutorial usaremos Views baseadas em classe.
Uma class based views é um padrão poderoso, que permite reutilizar funcionalidades comuns em views, além de nos ajudar a manter um código limpo.
Além disso, o DRF nos permite combinar um conjunto de views relacionadas em uma única view, isso chamamos de ViewSet.
Uma classe ViewSet é simplesmente uma View baseada em classe que não fornece nenhum método por padrão.
Neste tutorial iremos usar uma especialização da ViewSet, o ModelViewSet, que provê todas as funcionalidades básicas necessárias para nossa API.
Edite sua classe views.py localizada na pasta blog, para ficar semelhante ao código abaixo:
from django.shortcuts import render
from django.utils import timezone
from .models import Post
from rest_framework import viewsets
from .serializers import PostModelSerializer
def post_list(request):
posts = Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date')
return render(request, 'blog/post_list.html', {'posts': posts})
class PostModelViewSet(viewsets.ModelViewSet):
queryset = Post.objects.all().order_by('-title')
serializer_class = PostModelSerializer
O ModelViewSet exige que nós digamos pra ele qual serializador usar para criar a view, neste caso usaremos o serializador que criamos, PostModelSerializer.
Até agora já definimos nossos modelos(models.py), serializadores(serializers.py), views(views.py), porém como acessá-los? Através de urls(urls.py), também conhecidos como endpoints.
Como vocês viram no tutorial de django, as urls podem ser definidas manualmente e acopladas em suas views, porém a arquitetura REST segue um padrão, então seus endpoints devem atender a algumas regras.
Para não termos problemas com isso, o DRF nos dá de presente os ROUTERS, que juntos a um viewset fazem todo o roteamento das requisições.
Veremos no exemplo abaixo como funcionam no arquivo urls.py
do app blog:
from django.urls import path, include
from rest_framework import routers
from . import views
router = routers.DefaultRouter()
router.register('posts', views.PostModelViewSet)
urlpatterns = [
path('', views.post_list, name='post_list'),
path('api/v1/', include(router.urls))
]
Neste momento, salvamos os arquivos, e rodamos o nosso servidor local.
$ python manage.py runserver
E acessaremos o endpoint da API:
localhost:8000/api/v1
Um dos objetivos de construir uma API é dar segurança ao seu sistema, tendo controle de quem poderá usá-lo e como irá fazer isto. Para que isso ocorra, uma alternativa que o DRF te entrega é o uso de Tokens de autenticação, que os usuários recebem ao fazer uma requisição POST de login, enviando no corpo username e password.
O Token é uma chave criptografada que possui em si o usuário a quem pertence, e pode possuir um prazo de expiração. Após ter posse do token, este deve ser enviado no cabeçalho das requisições na seguinte forma:
"-H 'authorization: Token <seu-token>'"
para comandos CURL.
O servidor irá receber o token e verificar se é válido, em caso positivo, libera a requisição.
No DRF, precisamos criar um serializador para nossas requisições, bem como uma view e um endpoint.
No arquivo views.py
adicione:
from rest_framework.authtoken.views import ObtainAuthToken
from rest_framework.settings import api_settings
from .serializers import AuthTokenSerializer
class CreateTokenView(ObtainAuthToken):
serializer_class = AuthTokenSerializer
renderer_classes = api_settings.DEFAULT_RENDERER_CLASSES
Repare que nós ainda não escrevemos o nosso serializador, AuthTokenSerializer.
Para escrevê-lo, adicione ao arquivo serializers.py
:
from django.contrib.auth import authenticate
class AuthTokenSerializer(serializers.Serializer):
username = serializers.CharField()
password = serializers.CharField(
style={'input_type': 'password'},
trim_whitespace=False
)
def validate(self, attrs):
self.username = attrs.get('username')
self.password = attrs.get('password')
user = authenticate(
request=self.context.get('request'),
username=self.username,
password=self.password
)
if not user:
msg = 'Failure authentication'
raise serializers.ValidationError(msg, code='authentication')
attrs['user'] = user
return attrs
Por fim, precisamos criar o endpoint para criação do Token, então adicione ao arquivo urls.py
(do app blog):
path('api/v1/token/', views.CreateTokenView.as_view(), name='token')
Agora, é só fazer a requisição em localhost:8080/api/token/
com os parâmetros username e password no corpo.