Ao usar CoreAPI com DRF e DjangoFilterBackend
habilitado, o cliente tenta mapear todos os campos para uma ação create, update ou partial_update para os parâmetros de consulta também. Isso interrompe a capacidade do cliente de usar esses métodos.
Se tivermos uma solicitação que tenta criar um livro com um nome e nome também for um campo filtrável em nosso modelo:
# book views
class BookViewSet():
filter_fields = ('name',)
# ...
// schema
client.action('book', 'create', { 'name': 'My Awesome Book' });
Isso criará uma solicitação com o nome no parâmetro de URL e o corpo da solicitação. Este não é o comportamento esperado.
POST /api/book?name=My%20Awesome%20Book
name=My Awesome Book
Corrigimos isso em nosso código apontando nosso back-end de filtro DRF para uma substituição personalizada com o seguinte código:
class OnlyFilterOnReadDjangoFilterBackend(DjangoFilterBackend):
""" A filter backend that only allows for filtering by properties on
actions deemed as safe. This means that create, update, and partial_update
actions will not provide filter options.
"""
SAFE_ACTIONS = ('list', 'retrieve')
def get_schema_fields(self, view):
if view.action in self.SAFE_ACTIONS:
return super().get_schema_fields(view)
return []
Olá @Sonictherocketman. Obrigado pelo relatório.
Meu primeiro pensamento é que isso é um bug com a API do cliente - não é adequado distinguir entre os parâmetros da string de consulta e o corpo da solicitação ao construir a solicitação.
Em geral, apenas desabilitar a filtragem para ações não seguras não é correto. A filtragem ocorre ao estabelecer o conjunto de consultas base no qual uma atualização será feita.
Vou deixar isso em aberto por enquanto, só para pensar sobre isso.
Também acho que é um problema do cliente, mas quanto mais penso nisso, sinto que as ações não fazem sentido nas consultas de gravação (especialmente escrevendo para um recurso específico) e o esquema não deveria ter esses campos se eles não devem ser usados.
Obrigado pela resposta rápida e estou super interessado em seus pensamentos sobre isso.
Mais ou menos, acho que estamos limitados aqui por nossos desejos de geração de código _automágico_ superando a tecnologia (em seu estado atual).
Há muitas coisas que (ainda) não podemos fazer com esquemas (em qualquer um dos formatos disponíveis) que gostaríamos — por exemplo, com CoreAPI, ainda não podemos agrupar parâmetros para que um filtro de intervalo de datas seja exibido que eles estão relacionados. (Há muito mais que podemos fazer escrevendo esquemas à mão, mas ninguém quer fazer isso, é claro.)
Mas evolui, e à medida que o faz, o ferramental. Vai melhorar.
Que esta linha em particular:
client.action('book', 'create', { 'name': 'My Awesome Book' });
usa o mesmo dict para a string de consulta e o corpo da solicitação não é ótimo. Acho que é a abstração vazando. Você realmente quer construir esta solicitação _manualmente_, especificando parâmetros de consulta e corpo em lugares separados.
No momento, isso não é algo que possamos abordar aqui. Mais uma vez obrigado pelo relatório.
Comentários muito úteis
Olá @Sonictherocketman. Obrigado pelo relatório.
Meu primeiro pensamento é que isso é um bug com a API do cliente - não é adequado distinguir entre os parâmetros da string de consulta e o corpo da solicitação ao construir a solicitação.
Em geral, apenas desabilitar a filtragem para ações não seguras não é correto. A filtragem ocorre ao estabelecer o conjunto de consultas base no qual uma atualização será feita.
Vou deixar isso em aberto por enquanto, só para pensar sobre isso.