class BooksFilter(filters.FilterSet):
class Meta:
model = Books
Ao omitir a opção fields
em uma classe de conjunto de filtros (como acima), todos os campos do modelo serão incluídos no conjunto de filtros. Isso pode levar ao vazamento de informações quando usado em conjunto com DRF, onde o formulário é renderizado na API navegável.
Tanto o Django quanto o DRF exigem que os campos sejam especificados explicitamente em formulários/serializadores devido aos possíveis problemas de segurança. Isso também deve ser necessário em conjuntos de filtros django-filter.
http://www.django-rest-framework.org/api-guide/serializers/#specifying -which-fields-to-include
https://docs.djangoproject.com/en/1.10/topics/forms/modelforms/#selecting -the-fields-to-use
Fico feliz em contribuir com um PR ou explicar mais sobre em quais situações isso pode levar ao vazamento de informações, se necessário.
@nip3o Sim. Feliz em ver isso.
Eu também gostaria que os campos exigissem filtros declarados, conforme DRF, enquanto você está nisso... 😉
btw - o vazamento de dados foi parcialmente resolvido pelo #451. No momento, você deve ver avisos de descontinuação sobre comportamento indefinido/alterado. Na versão 1.0, o novo comportamento é que um ausente Meta.fields
ou Meta.fields = None
não faz nada.
Eu também gostaria que os campos exigissem filtros declarados, conforme DRF, enquanto você está nisso
Não tenho certeza de como isso funcionaria com a sintaxe dict para Meta.fields
. por exemplo:
class UserFilter(filters.FilterSet):
username = filters.CharFilter()
class Meta:
model = User
fields = {
'name': ['contains', 'startswith', 'endswith', ...'],
???
}
Não tenho certeza de como isso funcionaria com a sintaxe dict
De fato.
Ainda estou meio :-1: nisso. Não vejo uma maneira de resolver a sintaxe dict Meta.fields
com filtros declarados. Pelo menos, não de uma maneira que não seja estranha:
class UserFilter(filters.FilterSet):
username = filters.CharFilter(name='username', lookup_expr='exact')
username_like = filters.CharFilter(name='username', lookup_expr='icontains')
relevance = filters.CharFilter(method='filter_relevance')
class Meta:
model = User
fields = {
'name': ['contains', 'startswith', 'endswith', ...'],
'username': ['exact'], # match w/ the lookup_expr?
'username_like': ['icontains'],
'relevance': [???] # What about method filters?
}
Além disso, esse requisito gera problemas para campos de modelo personalizados que não herdam uma classe de campo encontrada no FilterSet.FILTER_DEFAULTS
. Os campos personalizados exigiriam o seguinte:
class NetworkSettingFilter(FilterSet):
mask = MaskFilter(...)
class Meta:
model = NetworkSetting
fields = ['mask']
filter_overrides = {
SubnetMaskField: {'filter_class': MaskFilter},
}
# vs.
class NetworkSettingFilter(FilterSet):
mask = MaskFilter(...)
class Meta:
model = NetworkSetting
Nota lateral: este ponto posterior é algo que _poderíamos_ corrigir. Teríamos que reescrever a geração automática para se comportar como os serializadores do DRF em vez de como os formulários de modelo do Django. De qualquer forma, minha principal preocupação é o conflito de sintaxe.
OK. Vamos deixar por enquanto.
Gosto da proposta original. Estou inclinado a definir o escopo para _Se fields
for uma lista..._ Mas preciso pensar um pouco mais.
Um pouco de idas e vindas, mas vou refazer este marco apenas para a edição original .
Ou fields
ou exclude
devem ser declarados. fields = '__all__'
deve ser o mínimo.
(Não impor que as listas correspondam é algo a que podemos voltar.)
O código DRF relevante está aqui :
assert not (fields is None and exclude is None), (
"Creating a ModelSerializer without either the 'fields' attribute "
"or the 'exclude' attribute has been deprecated since 3.3.0, "
"and is now disallowed. Add an explicit fields = '__all__' to the "
"{serializer_class} serializer.".format(
serializer_class=self.__class__.__name__
),
)
Precisamos de uma adição semelhante em filters_for_model
:
# Setting exclude with no fields implies all other fields.
if exclude is not None and fields is None:
fields = ALL_FIELDS
Ele precisará ser preterido para começar.
Ou
fields
ouexclude
devem ser declarados.fields = '__all__'
deve ser o mínimo.
Eu definitivamente posso ficar por trás disso. Atualmente trabalhando em um PR.
Frio.
Pensando nisso, não se preocupe com a depreciação. É uma pequena mudança, em uma grande mudança de versão. Apenas certifique-se de chamá-lo nas notas de alteração. 👍🏽
Pensando nisso, não se preocupe com a depreciação. É uma pequena mudança, em uma grande mudança de versão. Apenas certifique-se de chamá-lo nas notas de alteração.
A intenção é um pouco diferente, mas na verdade abordamos isso aqui .
Além disso, atualmente refatorando filters_for_model
para não tentar a geração de filtros para filtros declarados. (Isso é relevante para o exemplo de sub-rede/máscara em que fields = ['mask']
geraria uma exceção desnecessária.
Fechado por #550
Comentários muito úteis
btw - o vazamento de dados foi parcialmente resolvido pelo #451. No momento, você deve ver avisos de descontinuação sobre comportamento indefinido/alterado. Na versão 1.0, o novo comportamento é que um ausente
Meta.fields
ouMeta.fields = None
não faz nada.