Esta seção descreve a implementação de funcionalidades de paginação e filtragem para a listagem de usuários na API, tornando-a mais flexível e eficiente para lidar com grandes volumes de dados.
Para APIs que retornam listas de recursos, é crucial implementar mecanismos de paginação para evitar sobrecarregar o cliente e o servidor com grandes respostas. A filtragem, por sua vez, permite que os clientes solicitem apenas os dados relevantes, melhorando a experiência do usuário e a performance da aplicação.
Na Arquitetura Limpa, esses controles devem ser introduzidos nas camadas de Aplicação (nos casos de uso, que orquestram a lógica) e de Infraestrutura (nos repositórios, que interagem com o mecanismo de persistência), e expostos na camada de Apresentação (API).
A implementação envolverá as seguintes alterações:
Camada de Aplicação: Modificar o ListUsersRequest e ListUsersResponse para incluir parâmetros de paginação (offset, limit) e filtragem (ex: search_query). O ListUsersUseCase será atualizado para utilizar esses parâmetros.
Camada de Domínio (Interface): Atualizar a interface UserRepository com um novo método para obter usuários paginados e filtrados.
Camada de Infraestrutura: Implementar o método de paginação e filtragem no DjangoUserRepository, utilizando recursos do ORM do Django.
Camada de Apresentação (API): Adaptar a UserListAPIView e seus serializers para receber os parâmetros de paginação e filtragem via requisição HTTP e formatar a resposta com metadados de paginação.
Testes de Integração: Adicionar testes para validar o funcionamento da paginação e filtragem na API.
3. Alterações na Camada de Aplicação (Casos de Uso)¶
Modificamos os DTOs ListUsersRequest e ListUsersResponse para incluir os parâmetros de paginação (offset, limit) e filtragem (search_query), além dos metadados de paginação na resposta.
O ListUsersUseCase foi modificado para aceitar os novos parâmetros de ListUsersRequest e delegar a lógica de paginação e filtragem ao repositório, retornando os metadados de paginação na ListUsersResponse.
# project/core/domain/use_cases/user_use_cases.pyfromcore.domain.data_accessimportUserRepositoryfromcore.domain.entities.userimportUserasDomainUserfromcore.domain.use_cases.generic_use_casesimportCreateUserResponse# Necessário para o ListUsersResponsefromdataclassesimportdataclassfromtypingimportOptional,List# Adicionado List aqui@dataclassclassListUsersRequest:offset:int=0limit:int=10search_query:str|None=None@dataclassclassListUsersResponse:users:list[CreateUserResponse]total_items:intoffset:intlimit:intclassListUsersUseCase:def__init__(self,user_repository:UserRepository):self.user_repository=user_repositorydefexecute(self,request:ListUsersRequest)->ListUsersResponse:users_domain,total_items=self.user_repository.get_all_paginated_filtered(offset=request.offset,limit=request.limit,search_query=request.search_query)users_response=[CreateUserResponse(id=user.id,email=user.email,first_name=user.first_name,last_name=user.last_name,is_active=user.is_active,is_staff=user.is_staff,is_superuser=user.is_superuser,)foruserinusers_domain]returnListUsersResponse(users=users_response,total_items=total_items,offset=request.offset,limit=request.limit,)
4. Alterações na Camada de Domínio (Interface de Repositório)¶
Adicionamos o método get_all_paginated_filtered à interface UserRepository, que permite obter usuários com base em parâmetros de paginação e filtragem, retornando uma tupla contendo a lista de usuários e o total de itens.
A implementação do DjangoUserRepository agora inclui o método get_all_paginated_filtered, que utiliza o ORM do Django para aplicar a filtragem por email, first_name e last_name (case-insensitive) e a paginação (offset e limit).
a. Serializers (project/core/api/v1/serializers/user.py)¶
Criamos um ListUsersRequestSerializer para validar os parâmetros de query de paginação e filtragem, e atualizamos o UserListResponseSerializer para incluir os metadados de paginação na resposta.
A UserListAPIView foi adaptada para utilizar o ListUsersRequestSerializer para validar os parâmetros de paginação e filtragem da requisição, e passa esses parâmetros para o ListUsersUseCase.
Adicionamos testes de integração em project/core/tests/integration/test_user_api.py para validar o comportamento da API com as novas funcionalidades de paginação e filtragem.
# project/core/tests/integration/test_user_api.py# ... imports e setUp ...classUserAPITest(APITestCase):# ... setUp e outros testes ...deftest_list_users_pagination_limit(self):headers=self.get_auth_headers(self.admin_access_token)response=self.client.get(f"{self.user_list_url}?limit=5",**headers,format="json")self.assertEqual(response.status_code,status.HTTP_200_OK)self.assertEqual(len(response.data["items"]),5)self.assertEqual(response.data["limit"],5)self.assertEqual(response.data["offset"],0)self.assertGreaterEqual(response.data["total_items"],15)
# project/core/tests/integration/test_user_api.py# ... imports e setUp ...classUserAPITest(APITestCase):# ... setUp e outros testes ...deftest_list_users_filter_by_email(self):headers=self.get_auth_headers(self.admin_access_token)search_email=self.test_users[0].emailresponse=self.client.get(f"{self.user_list_url}?search_query={search_email}",**headers,format="json")self.assertEqual(response.status_code,status.HTTP_200_OK)self.assertEqual(len(response.data["items"]),1)self.assertEqual(response.data["items"][0]["email"],search_email)
A implementação da paginação e filtragem para a listagem de usuários seguiu os seguintes passos:
Criação de Novo Arquivo de Documentação: O arquivo docs/development/pagination-filtering.md foi criado para descrever a estratégia de paginação e filtragem.
Atualização de config/mkdocs.yml: O novo arquivo de documentação foi adicionado à navegação do MkDocs.
Atualização de Casos de Uso (ListUsersUseCase): ListUsersRequest e ListUsersResponse foram modificados para incluir parâmetros de paginação (offset, limit) e filtragem (search_query). O ListUsersUseCase foi adaptado para utilizar esses parâmetros e delegar a lógica ao repositório.
Atualização da Interface de Repositório (UserRepository): O método abstrato get_all_paginated_filtered foi adicionado à interface UserRepository.
Atualização da Implementação de Repositório (DjangoUserRepository): O método get_all_paginated_filtered foi implementado, utilizando o ORM do Django (com Q para filtragem icontains) para aplicar a lógica de paginação e filtragem.
Atualização de Serializers da API: Um ListUsersRequestSerializer foi criado para validar os parâmetros de query de entrada, e o UserListResponseSerializer foi atualizado para incluir os metadados de paginação (total_items, offset, limit) na resposta.
Atualização de Views da API (UserListAPIView): A UserListAPIView foi modificada para utilizar o ListUsersRequestSerializer para processar os parâmetros da requisição e passar os dados para o ListUsersUseCase.
Atualização de Testes de Integração: Novos testes foram adicionados em project/core/tests/integration/test_user_api.py para validar o funcionamento da paginação e filtragem nos endpoints da API.
Com a paginação e filtragem implementadas e documentadas, a API de listagem de usuários torna-se mais flexível e eficiente.