class BooksFilter(filters.FilterSet):
class Meta:
model = Books
Lorsque vous omettez l'option fields
dans une classe de jeu de filtres (comme ci-dessus), tous les champs du modèle seront inclus dans le jeu de filtres. Cela peut entraîner une fuite d'informations lorsqu'il est utilisé conjointement avec DRF, où le formulaire est rendu dans l'API navigable.
Django et DRF exigent tous deux que les champs soient spécifiés explicitement dans les formulaires/sérialiseurs en raison des problèmes de sécurité potentiels. Cela devrait également être requis dans les jeux de filtres 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
Je suis heureux de contribuer avec un PR ou d'expliquer plus en détail dans quelles situations cela peut conduire à une fuite d'informations, si nécessaire.
@nip3o Oui. Heureux de voir ça.
J'aimerais aussi que les champs nécessitent des filtres déclarés, selon DRF, tant que vous y êtes... 😉
btw - la fuite de données a été partiellement résolue par #451. À l'heure actuelle, vous devriez voir des avertissements d'obsolescence concernant un comportement indéfini/changeant. Dans la version 1.0, le nouveau comportement est qu'un Meta.fields
ou Meta.fields = None
absent ne fait rien.
J'aimerais également que les champs nécessitent des filtres déclarés, conformément au DRF, pendant que vous y êtes
Je ne sais pas comment cela fonctionnerait avec la syntaxe dict pour Meta.fields
. par exemple:
class UserFilter(filters.FilterSet):
username = filters.CharFilter()
class Meta:
model = User
fields = {
'name': ['contains', 'startswith', 'endswith', ...'],
???
}
Je ne sais pas comment cela fonctionnerait avec la syntaxe dict
En effet.
Je suis toujours un peu :-1: à ce sujet. Je ne vois pas de moyen de résoudre la syntaxe dict Meta.fields
avec des filtres déclarés. Du moins, pas d'une manière qui ne soit pas gênante :
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?
}
De plus, cette exigence se heurte à des problèmes pour les champs de modèle personnalisés qui n'héritent pas d'une classe de champ trouvée dans le FilterSet.FILTER_DEFAULTS
. Les champs personnalisés nécessiteraient les éléments suivants :
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
Remarque : ce dernier point est quelque chose que nous _pourrions_ corriger. Nous devrions réécrire la génération automatique pour qu'elle se comporte comme les sérialiseurs de DRF au lieu des formulaires modèles de Django. Quoi qu'il en soit, ma principale préoccupation est le conflit de syntaxe.
D'ACCORD. Laissons cela pour l'instant.
J'aime la proposition originale. Je suis enclin à l'étendre à _Si fields
est une liste..._ Mais je dois y réfléchir un peu plus.
Un peu d'allers-retours, mais je vais refaire le point juste pour le numéro d'origine .
fields
ou exclude
doit être déclaré. fields = '__all__'
devrait être le minimum.
(Ne pas imposer que les listes correspondent est quelque chose sur lequel nous pouvons revenir.)
Le code DRF correspondant est ici :
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__
),
)
Nous avons besoin d'un ajout similaire dans filters_for_model
:
# Setting exclude with no fields implies all other fields.
if exclude is not None and fields is None:
fields = ALL_FIELDS
Il devra être obsolète pour commencer.
fields
ouexclude
doit être déclaré.fields = '__all__'
devrait être le minimum.
Je peux certainement être derrière ça. Travaille actuellement sur un PR.
Frais.
En y réfléchissant, ne vous inquiétez pas de la dépréciation. C'est un petit changement, sur un changement de version majeur. Assurez-vous simplement de l'appeler dans les notes de modification. 👍🏽
En y réfléchissant, ne vous inquiétez pas de la dépréciation. C'est un petit changement, sur un changement de version majeur. Assurez-vous simplement de l'appeler dans les notes de modification.
L'intention est légèrement différente, mais nous avons en fait couvert cela ici .
En outre, refactoring actuellement filters_for_model
pour ne pas tenter de générer des filtres pour les filtres déclarés. (Ceci est pertinent pour l'exemple de sous-réseau/masque où fields = ['mask']
lèverait une exception inutile.
Fermé par #550
Commentaire le plus utile
btw - la fuite de données a été partiellement résolue par #451. À l'heure actuelle, vous devriez voir des avertissements d'obsolescence concernant un comportement indéfini/changeant. Dans la version 1.0, le nouveau comportement est qu'un
Meta.fields
ouMeta.fields = None
absent ne fait rien.