Skip to content

Conversation

@LeandroJatai
Copy link
Member

@LeandroJatai LeandroJatai commented Oct 29, 2025

Mixin de Serializer que implementa expansão dinâmica de campos via parâmetros de query string:

  • expand: expande os campos informados
  • include: inclui apenas os campos informados
  • exclude: exclui os campos informados

Exemplos:

  • ?expand=campo1;campo2.sub_campo1,sub_campo2;campo3.sub_campo1.sub_sub_campo1,sub_sub_campo2
  • ?include=campo1;campo2.sub_campo1,sub_campo2;campo3.sub_campo1.sub_sub_campo1,sub_sub_campo2
  • ?exclude=campo1;campo2.sub_campo1,sub_campo2;campo3.sub_campo1.sub_sub_campo1,sub_sub_campo2
  • ?expand=campo1&include=campo1.id,name&exclude=campo1.secret_field

Onde:

  • campo1, campo2, campo3 são campos do model raiz
  • sub_campo1, sub_campo2 são campos relacionados do campo2
  • sub_sub_campo1, sub_sub_campo2 são campos relacionados do sub_campo1

Ou seja:

  • ";" separa campos independentes
  • "," separa campos relacionados do mesmo campo pai
  • "." indica aprofundamento do campo

e ainda:

  • expand pode ser usado para expansão direta, ou seja, campo1.sub_campo1 já expande campo1
  • expand, include e exclude podem ser usados juntos na mesma requisição
  • include e exclude só funcionam em subniveis se o campo pai estiver expandido
  • include tem precedência sobre exclude e já remove todo o resto
  • exclude remove o campo do resultado final, mesmo que esteja em include
  • Se nenhum dos parâmetros for informado, nenhum campo será expandido
  • Filtros da API, paginação (page e page_size) e ordenação (o)
    podem ser usados normalmente para filtrar os resultados

Atenção:

  • A expansão não é aplicada para o model User do Django
  • A expansão não é aplicada para campos customizados que utilizam SerializerMethodField
  • Uma exceção é lançada e registrada no log caso ocorra algum erro na expansão de algum campo,
    inclusive devido a recursão infinita
  • A expansão automática de todos os campos relacionados (expand=all) está desabilitada
    por necessidade de controle mais refinado.
  • A expansão de campos relacionados ForeignKey e OneToOne é suportada.
  • A expansão de campos relacionados ManyToMany é suportada.
  • A expansão de campos relacionados reversos (related_name) não é suportada, mas pode ser implementada manualmente no serializer customizado, ou vir a ser implementada no futuro.
  • O mixin ApiFilterSetMixin não aplica filtros nas expansões
  • selection_related e prefetch_related não são aplicados automaticamente, podendo ser implementados manualmente na viewset customizada, ou vir a ser implementados no futuro (pretendo fazer esta impl o mais rápido possível). Observo que, mesmo sem a aplicação destes recursos, a expansão é mais eficiente que sem ela, pois, invariavelmente, se o client precisar desses dados, atualmente ele o fará em uma nova requisição que fará o select da mesma forma.

Exemplos reais em produção já sendo utilizados no fork cmjatai/cmj:

Exemplo de expansão única:
https://www.jatai.go.leg.br/api/materia/tramitacao/?expand=status
image

Expandindo dois campos em mesmo nível:
https://www.jatai.go.leg.br/api/materia/tramitacao/?expand=status;unidade_tramitacao_local
image

Expansão em níveis diferentes:
https://www.jatai.go.leg.br/api/materia/tramitacao/?expand=status;unidade_tramitacao_local.orgao
image

Expansão com inclusão em conjunto em terceiro nível:
https://www.jatai.go.leg.br/api/materia/tramitacao/?expand=status;unidade_tramitacao_local.orgao&include=unidade_tramitacao_local.orgao.id,nome,sigla
image

Expansão, exclusão e inclusão em níveis diferentes:
https://www.jatai.go.leg.br/api/materia/tramitacao/?expand=status;unidade_tramitacao_local.orgao&include=unidade_tramitacao_local.orgao.id,nome,sigla&exclude=unidade_tramitacao_local.link_detail_backend,comissao,parlamentar

Leitura completa deste link de exemplo:

  • expand faz com que status, unidade_tramitacao_local e unidade_tramitacao_local.orgao sejam expandidos
  • include informando que em orgao que ta dentro de unidade_tramitacao_local, seja recuperado apenas os campos id, nome e sigla de órgão.
  • exclude informando que em unidade_tramitacao_local os campos link_detail_backend, comissão, e parlamentar devem ser retirados da serialização
image

os exemplos acima foram feitos só no endpoint /api/materia/tramitacao mas a dinamica já funciona na api inteira

@LeandroJatai LeandroJatai force-pushed the impl_params_expand_include_exclude branch 3 times, most recently from a0e2354 to e023b85 Compare October 29, 2025 16:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant