Entendendo Django REST Framework

Review Django

  • Request de um browser chega no Django;
  • Consulta o urls.py base do projeto para encontrar o que será executado;
  • Consulta o urls.py da app (no caso) para encontrar a view que será executada;
  • Encontra a view dentro da app, que busca as informações no model;
  • Renderiza o template;
  • Retorna o template renderizado para o usuário.

Interlúdio: REST

REST: Recursos

Elementos são chamados "recursos" e fazem parte da URL.

  • Recurso usuários: /user;
  • Recurso orders: /order;
  • Recurso produtos: /product

REST: Recursos

Recursos específicos são indicados também na URL depois da URL base do recurso, apontados por sua chave principal.

  • Usuário 1: /user/1/
  • Produto ws-1243: /product/ws-1243/

REST: Recursos

Recursos podem estar aninhados.

  • /user/1/order: Todos os pedidos do usuário 1.
  • /user/1/order/2: Pedido 2 do usuário 1.

REST: Verbos/Ações

Ações sobre os recursos são indicadas pelo verbo HTTP:

  • GET: Recupera recursos;
  • POST: Cria recursos;
  • PUT: Altera (update) recursos;
  • DELETE: Apaga recursos;
  • PATCH: Altera recursos.

REST: Verbos

  Base recurso Recurso específico
GET Todos os elementos do recurso Dados do recurso específico

REST: Verbos

  Base recurso Recurso específico
POST Cria um recurso novo Não usado, mas poderia criar um recurso com a cahve indicada

REST: Verbos

  Base recurso Recurso específico
PUT Não usado Ataliza o registro inteiro do recurso

REST: Verbos

  Base recurso Recurso específico
DELETE Não usado, mas poderia apagar todos os recursos Apaga o recurso

REST: Verbos

  Base recurso Recurso específico
PATCH Não usado Atualiza campos específicos do recurso

REST: Exemplos

  • GET /user: Retorna todos os usuários do sistema.
  • POST /order: Cria um novo pedido.
  • DELETE /user/1/order/2: Apaga o pedido 2 do usuário 1.

De volta ao REST Framework

  • Request de um browser chega no Django;
  • Consulta o urls.py base do projeto para encontrar o que será executado;
  • Consulta o urls.py da app (no caso) para encontrar a view que será executada;
  • Continua acessando o urls.py do app, mas esse é complementado com Routers.

Routes


router = DefaultRouter()
router.register(r'base_resource', ModelViewSet)
urlpatterns = router.urls
                        

Onde:

  • base_resource: é a URL base de acesso ao recurso;
  • ModelViewSet: é um ViewSet criado em cima do modelo.

Por que "Routes"?

Para não precisar criar dois GETS, um POST, um PUT, um PATCH e um DELETE.

E o que diabos é um ViewSet?

ViewSet define as funções para cada um dos verbos dentro do resource:

  • list(self, request)
  • create(self, request)
  • retrieve(self, request, pk=None)
  • update(self, request, pk=None)
  • partial_update(self, request, pk=None)
  • destroy(self, request, pk=None)

ModelViewSet

Um ModelViewSet aplica as funções acima sobre um Model.


class ProductViewSet(viewsets.ModelViewSet):
    queryset = Product.objects.all()
    serializer_class = ProductSerializer
                        

Existe ainda ReadOnlyModelViewSet que só define as funções list() e retrieve().

Pera, pera... Serializer?

Serializers definem campos de resultados e sua validação, caso estejam sendo usados como entradas (assim como Forms são usados para validar entradas de dados por forms).


class UserSerializer(serializers.ModelSerializer):

    class Meta:
        model = Product
        fields = ('name', 'price')
                        

Fluxo REST Framework

  • Request de um browser chega no Django;
  • Consulta o urls.py base do projeto para encontrar o que será executado;
  • Consulta o urls.py da app (no caso) para encontrar a view que será executada;
  • Continua acessando o urls.py do app, mas esse é complementado com Routers;

Fluxo REST Framework (contd.)

  • Acerta o Serializer para validar a entrada (se houver);
  • Vai ou ViewModelSet para definr a execução;
  • Faz os requests necessários para o model;
  • Passa o resultado de novo pelo Serializer para converter para o formato de saída;
  • Retorna o request.

PS: Outras coisas legais

Vem com um serializador JSON como padrão, mas existem outros:

  • djangorestframework-yaml: Serializador/desserializador para YAML.
  • djangorestframework-xml: Serializador/desserializador para XML.

JSON


curl -H 'Accept: application/json; indent=4' \
    -u  admin:admin123 http://127.0.0.1:8000/users/
                        

{
    "count": 1,
    "next": null,
    "previous": null,
    "results": [
        {
            "url": "http://127.0.0.1:8000/users/1/",
            "username": "admin",
            "email": "",
            "groups": []
        }
    ]
                        

YAML


curl -H 'Accept: application/yaml' \
    -u  admin:admin123 http://127.0.0.1:8000/users/
                        

count: 1
next: null
previous: null
results:
- email: ''
  groups: []
  url: http://127.0.0.1:8000/users/1/
  username: admin
                        

XML


curl -H 'Accept: application/xml' \
    -u  jbiason:slowdown http://127.0.0.1:8000/users/
                        



    1
    
    
    
        
            http://127.0.0.1:8000/users/1/
            admin
            
            
        
    

                        

(Todos os casos, só foi alterado o header "Accept" no request; nenhuma alteração de código -- com exceção do settings.py para ativar os serializers.)