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.
Capítulo 1: Introdução, configuração e Hello World
Capítulo 2: Organizando as dependências e requerimentos
Capítulo 3: Configurando o pytest e nosso primeiro teste
Capítulo 4: Configurando o Makefile
Capítulo 5: Adicionando o MongoDB
Capítulo 6: Criando e testando o modelo de usuários
Capítulo 7: Criando usuários
Capítulo 8: Listando usuários Estamos aqui
Capítulo 9: Buscando usuários
Capítulo 10: Editando um usuário
Capítulo 11: Deletando um usuário
Capítulo 12: Autênticação por JWT
Capítulo 13: Criando um container Docker
Capítulo 14: Arquivos de configuração para Deploy na Digital Ocean
Capítulo 15: Automatizando o processo de deploy com Fabric
Capítulo 16: CI e CD com Jenkins, Python, Flask e Fabric
Capítulo 17: Utilizando o RabbitMQ com Flask e Sendgrid para enviar e-mails de boas vindas e ativar a conta do usuário
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