Django-filter: Löst eine Ausnahme aus, wenn Felder in FilterSet nicht angegeben sind

Erstellt am 28. Sept. 2016  ·  11Kommentare  ·  Quelle: carltongibson/django-filter

class BooksFilter(filters.FilterSet):
    class Meta:
        model = Books

Wenn die Option fields in einer Filterset-Klasse weggelassen wird (wie oben), werden alle Modellfelder in das Filterset aufgenommen. Dies kann zu Informationslecks führen, wenn es in Verbindung mit DRF verwendet wird, wo das Formular in der durchsuchbaren API gerendert wird.

Sowohl Django als auch DRF erfordern aufgrund der potenziellen Sicherheitsprobleme die explizite Angabe von Feldern in Formularen/Serialisierern. Dies sollte auch in Django-Filter-Filtersätzen erforderlich sein.
http://www.django-rest-framework.org/api-guide/serializers/#specifying-what-fields-to-include
https://docs.djangoproject.com/en/1.10/topics/forms/modelforms/#selecting-the-fields-to-use

Gerne trage ich mit einer PR bei oder erkläre bei Bedarf mehr darüber, in welchen Situationen dies zu Informationslecks führen kann.

ImprovemenFeature

Hilfreichster Kommentar

Übrigens - Datenlecks wurden teilweise von #451 behoben. Im Moment sollten Sie Verfallswarnungen über undefiniertes/änderndes Verhalten sehen. In 1.0 ist das neue Verhalten, dass ein abwesendes Meta.fields oder Meta.fields = None nichts bewirkt.

Alle 11 Kommentare

@nip3o Ja . Ich freue mich, dies zu sehen.

Ich möchte auch, dass Felder gemäß DRF deklarierte Filter erfordern, wenn Sie schon dabei sind ... 😉

Übrigens - Datenlecks wurden teilweise von #451 behoben. Im Moment sollten Sie Verfallswarnungen über undefiniertes/änderndes Verhalten sehen. In 1.0 ist das neue Verhalten, dass ein abwesendes Meta.fields oder Meta.fields = None nichts bewirkt.

Ich möchte auch, dass Felder gemäß DRF deklarierte Filter erfordern, wenn Sie schon dabei sind

Ich bin mir nicht sicher, wie dies mit der dict-Syntax für Meta.fields funktionieren würde. z.B:

class UserFilter(filters.FilterSet):
    username = filters.CharFilter()

    class Meta:
        model = User
        fields = {
            'name': ['contains', 'startswith', 'endswith', ...'],
            ???
        }

Ich bin mir nicht sicher, wie das mit der dict-Syntax funktionieren würde

In der Tat.

Ich bin immer noch irgendwie :-1: dabei. Ich sehe keine Möglichkeit, die Meta.fields -Diktatsyntax mit deklarierten Filtern aufzulösen. Zumindest nicht auf eine Weise, die nicht umständlich ist:

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?
        }

Darüber hinaus führt diese Anforderung zu Problemen bei benutzerdefinierten Modellfeldern, die keine in FilterSet.FILTER_DEFAULTS gefundene Feldklasse erben. Für benutzerdefinierte Felder wäre Folgendes erforderlich:

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

Nebenbemerkung: Dieser spätere Punkt ist etwas, das wir beheben _könnten_. Wir müssten die automatische Generierung umschreiben, damit sie sich wie die Serialisierer von DRF verhält, anstatt wie die Modellformulare von Django. In jedem Fall ist mein Hauptanliegen der Syntaxkonflikt.

OK. Lassen wir es jetzt.

Der ursprüngliche Vorschlag gefällt mir. Ich neige dazu, es auf _If fields is a list..._ abzugrenzen, aber ich muss noch ein wenig darüber nachdenken.

Ein bisschen hin und her, aber ich werde dies nur für die ursprüngliche Ausgabe wiederholen.

Es sollte entweder fields oder exclude deklariert werden. fields = '__all__' sollte das Minimum sein.

(Das Nichterzwingen, dass die Listen übereinstimmen, ist etwas, worauf wir zurückkommen können.)

Der relevante DRF-Code ist hier :

        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__
            ),
        )

Wir brauchen einen ähnlichen Zusatz in filters_for_model :

    # Setting exclude with no fields implies all other fields.
    if exclude is not None and fields is None:
        fields = ALL_FIELDS

Es muss zu Beginn veraltet sein.

Es sollte entweder fields oder exclude deklariert werden. fields = '__all__' sollte das Minimum sein.

Da kann ich auf jeden Fall dahinterstehen. Arbeite gerade an einer PR.

Cool.

Denken Sie darüber nach, machen Sie sich keine Sorgen über die Abschreibung. Es ist eine kleine Änderung, bei einer großen Versionsänderung. Stellen Sie einfach sicher, dass Sie es in den Änderungshinweisen erwähnen. 👍🏽

Denken Sie darüber nach, machen Sie sich keine Sorgen über die Abschreibung. Es ist eine kleine Änderung, bei einer großen Versionsänderung. Stellen Sie einfach sicher, dass Sie es in den Änderungshinweisen erwähnen.

Die Absicht ist etwas anders, aber wir haben das hier tatsächlich behandelt.

Außerdem wird derzeit filters_for_model umgestaltet, um keine Filtergenerierung für deklarierte Filter zu versuchen. (Dies ist relevant für das Subnetz/Masken-Beispiel, wo fields = ['mask'] eine unnötige Ausnahme auslösen würde.

Geschlossen von #550

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen