Problema
Conforme recomendado na postagem do blog Best Practices para projetar uma API RESTful pragmática , gostaria de adicionar um fields
parâmetro de consulta a uma API baseada no Django Rest Framework que permite ao usuário selecionar apenas um subconjunto de campos por recurso.
Exemplo
Serializer:
class IdentitySerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = models.Identity
fields = ('id', 'url', 'type', 'data')
Uma consulta regular retornaria todos os campos.
GET /identities/
[
{
"id": 1,
"url": "http://localhost:8000/api/identities/1/",
"type": 5,
"data": "John Doe"
},
...
]
Uma consulta com o fields
parâmetro deve retornar apenas um subconjunto dos campos:
GET /identities/?fields=id,data
[
{
"id": 1,
"data": "John Doe"
},
...
]
Uma consulta com campos inválidos deve ignorar os campos inválidos ou gerar um erro do cliente.
Objetivo
Isso é possível fora da caixa de alguma forma? Se não, qual é a maneira mais simples de implementar isso? Existe um pacote de terceiros que já faz isso?
fonte
QUERY_PARAMS
paraquery_params
nas versões recentes do Django, mas fora isso, funciona perfeitamente.requests
existe como membro decontext
. Enquanto faz na produção, não faz isso ao executar testes de unidade que criam os objetos manualmente.Esta funcionalidade está disponível em um pacote de terceiros .
Declare seu serializador assim:
Em seguida, os campos agora podem ser especificados (lado do cliente) usando argumentos de consulta:
A filtragem de exclusão também é possível, por exemplo, para retornar todos os campos, exceto id:
isenção de responsabilidade: eu sou o autor / mantenedor.
fonte
dbrgn
implementação tem algumas diferenças: 1. não suporta excluir comfields!=key1,key2
. 2. também modifica serializadores fora do contexto de solicitação GET, o que pode e irá interromper algumas solicitações PUT / POST. 3. não acumula campos comfields=key1&fields=key2
, por exemplo , o que é útil para aplicativos ajax. Ele também tem cobertura de teste zero, o que é um tanto incomum no OSS.serializers.py
views.py
fonte
Configure uma nova classe de serializador de paginação
Faça serializador dinâmico
Por último, use um mixin de imagens caseiras para suas APIViews
Solicitação
Agora, ao solicitar um recurso, você pode adicionar um parâmetro
fields
para mostrar apenas os campos especificados no url./?fields=field1,field2
Você pode encontrar um lembrete aqui: https://gist.github.com/Kmaschta/e28cf21fb3f0b90c597a
fonte
Você pode tentar REST dinâmico , que tem suporte para campos dinâmicos (inclusão, exclusão), objetos incorporados / sideload, filtragem, ordenação, paginação e muito mais.
fonte
Fornecemos essa funcionalidade em drf_tweaks / control-over-serialized-fields .
Se você usar nossos serializadores, tudo que você precisa é passar o
?fields=x,y,z
parâmetro na consulta.fonte
Para dados aninhados, estou usando Django Rest Framework com o pacote recomendado na documentação , drf-flexfields
Isso permite que você restrinja os campos retornados nos objetos pai e filho. As instruções no leia-me são boas, apenas algumas coisas a serem observadas:
O URL parece precisar do / assim '/ pessoa /? Expand = país & campos = id, nome, país' em vez de como escrito no readme '/ pessoa? Expand = país & campos = id, nome, país'
A nomenclatura do objeto aninhado e seu nome relacionado precisam ser completamente consistentes, o que não é necessário de outra forma.
Se você tiver 'muitos', por exemplo, um país pode ter muitos estados, você precisará definir 'muitos': True no serializador conforme descrito nos documentos.
fonte
Se você quiser algo flexível como GraphQL, você pode usar django-restql . Ele oferece suporte a dados aninhados (simples e iteráveis).
Exemplo
Uma solicitação regular retorna todos os campos.
GET /users
Uma solicitação com o
query
parâmetro, por outro lado, retorna apenas um subconjunto dos campos:GET /users/?query={id, username}
Com django-restql você pode acessar campos aninhados de qualquer nível. Por exemplo
GET /users/?query={id, username, date_joined{year}}
Para campos aninhados iteráveis, por exemplo, grupos de usuários.
GET /users/?query={id, username, groups{id, name}}
fonte