Django-filter: Lever une exception si les champs ne sont pas donnés dans FilterSet

Créé le 28 sept. 2016  ·  11Commentaires  ·  Source: carltongibson/django-filter

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.

ImprovemenFeature

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 ou Meta.fields = None absent ne fait rien.

Tous les 11 commentaires

@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 ou exclude 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

Cette page vous a été utile?
0 / 5 - 0 notes