Skip to content

rauldosS/django-rest-framework

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

34 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🏫 Django REST Framework

Projeto exemplo para entendimento e criação de aplicações Django com Django REST Framework.

Django REST Framwork

🗂️ Sumário


📚 Conceitos

📕 API

Interface de comunicação de aplicações de forma programática.

📗 REST - Representation Stare Transfer

HTTP é um design sem estado, ou seja, toda requisição é única. A responsabilidade de lembrar dos estados é do cliente.

📁 Introdução às APIs REST

📘 Endpoints

🔖 Substantivos

Gramática da língua portuguesa tem tudo a ver com endpoints, pois usamos substantivos e verbos para criá-los.

🔖 Resources (recursos)

Um 'resource' pode ser, por exemplo, um modelo da nossa aplicação:

  • Categorias
  • Produtos

Nós fazemos as operações CRUD através de URI específicas na nossa aplicação, por exemplo:

  • sistema.com.br/api/v1/produtos
  • sistema.com.br/api/v1/categorias

Estas URIs são os endpoints

🗃️ Boas práticas na criação de endpoints

Um endpoint pode representar uma coleção de registros ou um registro individual.

Coleção

sistema.com.br/api/v1/produtos

Individual

sistema.com.br/api/v1/produtos/42

🔖 Verbos (CRUD)

Indica uma ação.

  • C Create POST
  • R Read GET
  • U Update PUT
  • D Delete DELETE

📁 Entendendo os Endpoints

📙 Requests

As requisições (requests) é a solicitação ao servidor.

Exemplo:

/api/v1/produtos?order=desc&limit=10

Tudo que vem depois do ? é chamado de querystring

🔖 Cabeçalhos da request

  • Accept: Específica o formato de arquivo.
  • Accept-Language: Define lingua de retorno.
  • Cache-Control: Específica se o conteúdo pode ser consumido do cache e em quanto tempo o cache é atualizado.

application/json define um padrão de retorno.

🔖 Versão da API

/api/v1/produtos
/api/v2/produtos

📁 Entendendo as Requests

📘 Responses

Preparar a Resposta.

Detalhes avaliados da solicitação:

  • Na requisição existe query string?
  • Qual foi o verbo HTTP que realizou a ação?
  • Quai são os dados do cabeçalho?
  • Qual o formato requisitado?
  • Preparar os dados da coleção ou indivíduo do recurso solicitado.

Dados retornados:

  • data (dados)
  • Cabeçalho
    • Content-Type: Accept encaminhado.
    • Las-Modified: Data de criação ou última modificação.
    • Expires: Até quando este dado pode ser considerado atual
    • Status: 200 OK (código de status HTTP)

📁 Entendendo as Responses

🔐 Segurança

  • Fazendo uso de cache.
  • Limitar número de requisições por período (segundos).
  • Autenticação (quem você é)
    • Token (chave publica)
  • Autorização (o que você pode fazer)

📁 Entendendo sobre a segurança de APIs REST

📘 Django REST Framework (DRF)

Model Serialization, DRF mapeia os Django Models e provê uma facilidade muito grande a trabalhar com os objetos Python e serializar/deserializar para JSON.


📖 Instalação e configuração básica

  1. Instale o django-rest-framework
pip install djangorestframework markdown django-filter
pip freeze > requirements.txt
  1. Adicionar rest_framework em INSTALLED_APPS no arquivo escola/settings.py
[
    'django_filters',
    'rest_framework'
]
  1. Adicionar configurações de DRF no arquivo escola/settings.py
# DRF
REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.SessionAuthentication',
    ),
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticatedOrReadOnly',
    )
}
  1. Incluir URLs padrão em urlpatterns no arquivo escola/urls.py
path('auth/', include('rest_framework.urls')),

📊 Configuração intermediária

🔨 ViewSets

📁 ViewSets

🔨 Routers

  • Otimiza a criação de urls, gera automaticamente através do router as operações CRUD de apenas um modelo.
  • Sobrescreva o método get para acessar, por exemplo, todas a avaliações de um determinado curso (v2/cursos/1/avaliacoes).

🔨 Relações

Existem 3 formas de retornar modelos relacionados em sua API.

🔖 Nested Relationship

Retorna os objetos conforme parametrizado no seu Serializer das avaliações relacionadas.

avaliacoes = AvaliacaoSerializer(many=True, read_only=True)

🔖 HyperLinked Related Field

Adicionar um link para acesso das avaliações relacionadas.

avaliacoes = serializers.HyperlinkedRelatedField(
    many=True,
    read_only=True,
    view_name='avaliacao-detail'
)

🔖 Primary Key Related Field

Adiciona apenas a chave primária (id) das avaliações relacionadas.

avaliacoes = serializers.PrimaryKeyRelatedField(many=True, read_only=True)

🔨 Paginação

Em escola/settings.py adicione ao REST_FRAMEWORK:

REST_FRAMEWORK = {
    ...,
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
    'PAGE_SIZE': 2
}

Adiciona automaticamente 3 atributos ao retorno.

{
    "count": "<int:contagem de páginas>",
    "next": "<link:página anterior>",
    "previous": "<link:próxima página>",
}

Obs: Em métodos sobrescritos você deverá adicionar manualmente a paginação conforme exemplo que ocorre em CursoViewSet:

@action(detail=True, methods=['get'])
    def avaliacoes(self, request, pk=None):
        self.pagination_class.page_size = 2
        avaliacoes = Avaliacao.objects.filter(curso_id=pk)
        page = self.paginate_queryset(avaliacoes)

        if page is not None:
            serializer = AvaliacaoSerializer(page, many=True)
            return self.get_paginated_response(serializer.data)

        serializer = AvaliacaoSerializer(avaliacoes, many=True)
        return Response(serializer.data)

🔐 Configuração avançada

🔨 Autenticação via Token

Configurações em escola/settings.py:

  1. Adicionar aos INSTALLED_APPS:
{
    ...,
    'rest_framework.authtoken',
    ...
}
  1. Comentar autenticação via sessão do REST_FRAMEWORK e adicionar:
'DEFAULT_AUTHENTICATION_CLASSES': (
    # 'rest_framework.authentication.SessionAuthentication',
    'rest_framework.authentication.TokenAuthentication',
),
  1. Realizar migração
python manage.py migrate

🔖 Para sobrescrever o modelo User utilize

from rest_framework.authtoken.models import Token
from django.contrib.auth.models import User

admin = User.objects.get(id=1)

token = Token.objects.create(user=admin)

print(token.key)

Token Admin: 11c573b2dab073aef36698a9600a43aa8cb70d99

Obs: É possível realizar a criação via Administração do Django

🔨 Fazendo uso de permissões

Permissões dizem respeito aos verbos HTTP (CRUD) que o usuário tem permissão para executar.

Através do Administração do Django é possível realizar essa configuração de permissão sobre um modelo específico para cada usuário sem tornar o usuário administrador.

🔖 Criação de sua própria classe que define permissões

  1. Criação de um arquivo chamado permissions.py no diretório do app 1.1 Exemplo em cursos/permissions.py
  2. Importação de módulo criado nas views e inserção no início do ViewSet 2.1 Exemplo em cursos/views.py
from rest_framework import permissions

class CursoViewSet(viewsets.ModelViewSet):
    permission_classes = (
        EhSuperUser,
        permissions.DjangoModelPermissions,
    ),
    ...

🔨 Limitando número de requisições com Throttling

Similar a permissões, porém ele vai limitar as requisições por um determinado período para os clientes.

A configuração será global configurada no REST_FRAMEWORK em cursos/settings.py:

  • Anônimos podem fazer podem fazer 5 requisições por minuto e
  • Usuários autenticados podem fazer 10 requisições por minuto.
{
    ...,
    'DEFAULT_THROTTLE_CLASSES': (
        'rest_framework.throttling.AnonRateThrottle',
        'rest_framework.throttling.UserRateThrottle',
    ),
    'DEFAULT_THROTTLE_RATES': {
        'anon': '5/minute',  # second, day, month, year
        'user': '10/minute'
    }
}

🔨 Customizando a validação dos dados

Restrição: Avaliações não podem ser maior que 5 (avaliacao).

Criação de uma avaliação:

{
	"curso": 2,
	"nome": "Maria da Silva",
	"email": "maria@gmail.com",
	"avaliacao": 9
}

Retorno:

{
	"avaliacao": [
		"A avaliação precisa ser um inteiro entre 1 e 5"
	]
}
  1. Em cursos/seralizers.py criar a validação para a classe 1.1 A função por padrão deve começar com validate_
def validate_avaliacao(self, valor):
    if valor in range(1, 6):  # 1, 2, 3, 4, 5
        return valor
    raise serializers.ValidationError('A avaliação precisa ser um inteiro entre 1 e 5')

🔨 Customizando a serialização dos dados

Adicionar atributo no retorno com a média das avaliações

  1. Criar atributo e especificar o tipo
media_avaliacoes = serializers.SerializerMethodField()
  1. Adicionar na lista de dados que serão apresentados
fields = (
    'media_avaliacoes'
)
  1. Criar função 3.1 Nome da função iniciado em _get e 3.2 Restante do nome é o atributo que será criado
def get_media_avaliacoes(self, obj):
    media = obj.avaliacoes.aggregate(Avg('avaliacao')).get('avaliacao__avg')

    if media is None:
        return 0
    return round(media * 2) / 2

🔖 Sugestão de performance

Ao inves de criar uma função para atualizar a média em cada requisição, criar um campo no modelo e atualizar o campo a cada atualização.


👨‍💻 Testando APIs

A pasta tests no diretório raiz contém todos os testes com descrição em cada arquivo.

Crie testes que façam sentido para a sua aplicação!

🔨 Instalando e utilizando o módulo requests

Módulo para fazer requisições.

pip install requests

📁 Arquivos de testes para requests

🔨 Testando os métodos GET, POST, PUT e DELETE

🔨 Instalando e utilizando o módulo JSONPATH

pip install jsonpath

Vantagem: acessar diretamente os dados com maior facilidade e realizar filtros nativamente

🔨 Testando com Pytest

pip install pytest

📁 Pytest

Comando para executar testes pelo arquivo pytest:

pytest .\tests\test_pytest.py

Obs: o pk/id dos métodos PUT e POST (requests) deve ser atualizado para realização dos testes.

🔨 Insominia

📁 JSON de importação Insominia


🕹️ Abrir e rodar o projeto

Instruções necessárias para abrir e executar o projeto

Instale o Python 3

  1. Clone o repositório e entre na pasta:
git clone https://github.com/rauldosS/django-rest-framework.git
cd/django-rest-framework
  1. Crie um ambiente virtual:

Linux

virtualenv <nome_da_virtualenv>

Windows

python -m venv <nome_da_virtualenv>
  1. Ative o ambiente virtual que você acabou de criar:

Linux

source <nome_da_virtualenv>/bin/activate

Windows

.\<nome_da_virtualenv>\Scripts\activate
  1. Instale os pacotes de desenvolvimento local:
pip install -r requirements.txt
  1. Execute as migrações:
python manage.py migrate

Rode o servidor de desenvolvimento:

python manage.py runserver

🔖 Execução no ambiente Windows

alt text

About

Escola com Django REST Framework

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages