Lucas Simon

Web Developer. lucassrod@gmail.com

Série API em Flask - Parte 8 - Listando usuários

A partir deste até o Capítulo 11: Deletando um usuário as rotas serão administrativas. Ou seja somente quem for da role.admin = true poderá acessar essas rotas. A validação e autenticação será feita posteriormente, por agora, vamos apenas construir os recursos necessários.

Para entendimento, segue os capítulos que serão abordados.

O repositório com todo o código fonte esta aqui. Os capítulos estão em branches.

Configurando a rota

Em nosso arquivo apps/api.py vamos adicionar nosso recurso:


# Importar o recurso
from apps.users.resources_admin import AdminUserPageList


def configure_api(app):
    # ...

    # rotas para os admins
    api.add_resource(AdminUserPageList, '/admin/users/<int:page_id>')

    #...

Observe que colocamos um parametro nomeado na url <int:page_id>. Ele é usado no recurso AdminUserPageList que será criado logo abaixo.

O recurso AdminUserPageList

Primeiro vou organizar essas rotas em um único módulo chamados apps/users/resources_admin.py. Esses recursos pouco se diferem um dos outros, apenas que no futuro quando formos realizar uma autenticação iremos validar pelo jwt recebido.

Após criar o arquivo adicione o código abaixo:

# -*- coding: utf-8 -*-

# Flask
from flask import request

# Third
from flask_restful import Resource
from mongoengine.errors import FieldDoesNotExist

# Apps
from apps.responses import resp_ok, resp_exception

from apps.messages import MSG_RESOURCE_FETCHED_PAGINATED

# Local
from .models import User
from .schemas import UserSchema


class AdminUserPageList(Resource):

    # Lembra-se do page_id criado na rota ele pode ser acessado como parâmetro
    # do metodo get

    def get(self, page_id=1):
        # inicializa o schema podendo conter varios objetos
        schema = UserSchema(many=True)
        # incializa o page_size sempre com 10
        page_size = 10

        # se enviarmos o page_size como parametro
        if 'page_size' in request.args:
            # verificamos se ele é menor que 1
            if int(request.args.get('page_size')) < 1:
                page_size = 10
            else:
                # fazemos um type cast convertendo para inteiro
                page_size = int(request.args.get('page_size'))

        try:
            # buscamos todos os usuarios da base utilizando o paginate
            users = User.objects().paginate(page_id, page_size)

        except FieldDoesNotExist as e:
            return resp_exception('Users', description=e.__str__())

        except Exception as e:
            return resp_exception('Users', description=e.__str__())

        # criamos dados extras a serem respondidos
        extra = {
            'page': users.page, 'pages': users.pages, 'total': users.total,
            'params': {'page_size': page_size}
        }

        # fazemos um dump dos objetos pesquisados
        result = schema.dump(users.items)

        return resp_ok(
            'Users', MSG_RESOURCE_FETCHED_PAGINATED.format('usuários'),  data=result.data,
            **extra
        )

Testando

$ http -v GET 0.0.0.0:5000/admin/users/1?page_size=40
GET /admin/users/1?page_size=40 HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate
Connection: keep-alive
Host: 0.0.0.0:5000
User-Agent: HTTPie/0.9.8



HTTP/1.0 200 OK
Content-Length: 331
Content-Type: application/json
Date: Thu, 11 Oct 2018 19:30:34 GMT
Server: Werkzeug/0.14.1 Python/3.6.5

{
    "data": [
        {
            "active": false,
            "cpf_cnpj": "",
            "email": "teste@teste.com",
            "full_name": "teste 1234"
        }
    ],
    "message": "Lista os/as usuários paginados(as).",
    "page": 1,
    "pages": 1,
    "params": {
        "page_size": 40
    },
    "resource": "Users",
    "status": 200,
    "total": 1
}

Podemos observar que é bem simples codificar uma paginação de resultados através do Flask e Mongo. Além disso é possível aplicar técnicas de cache para que não haja um grande consumo em chamadas de banco de dados. Porém vamos deixar isso para futuros capítulos.

Próximo artigo: Buscando usuários