Frage

Ich verwende django-filter mit Django-Rest-Framework Und ich versuche, einen Filter zu instanziieren, der die Nummernlisten akzeptiert, um das Abfragen festzulegen

generasacodicetagpre.

Wenn ich eine durch Kommas getrennte Liste der Ganzzahlen weiterleite, wird der Filter vollständig ignoriert.

Wenn ich eine einzelne Ganzzahl passiere, wird es durch den Django-Filter in Django-Formular-Validator gelangen und klagt:

generasacodicetagpre.

Gibt es eine Möglichkeit, ein Django-Filter-Objekt zu erstellen, das eine Liste der Ganzzahlen verarbeiten kann, und filtern Sie den AbfrageSet richtig herunter?

War es hilfreich?

Lösung

Zum Besseren oder schlechter habe ich einen benutzerdefinierten Filter erstellt:

generasacodicetagpre.

das verwendet wird wie:

generasacodicetagpre.

Jetzt akzeptiert meine Schnittstelle Kommas getrennte Listen von Ganzzahlen.

Andere Tipps

Ich weiß, dass dies ein alter Posten ist, aber es gibt jetzt eine bessere Lösung.Die Änderung, die es richtig macht, ist gepostet hier .

Sie fügten einen generationspflichtigen, einem generationspflichten und einem BaseInFilter hinzu.Die Dokumentation ist hier .

Big Picture, BaseFilter prüft für CSV, und wenn Sie mit einem anderen Filter gemischt werden, tut es, was Sie fragen.Ihr Code kann jetzt geschrieben werden wie:

generasacodicetagpre.

Hier ist eine komplette Lösung:

generasacodicetagpre.

According to a post in the django-filter issues:

from django_filters import Filter
from django_filters.fields import Lookup

class ListFilter(Filter):
    def filter(self, qs, value):
        return super(ListFilter, self).filter(qs, Lookup(value.split(u","), "in"))

I have personally used this without any issue in my projects, and it works without having to create a per-type filter.

Based on @yndolok answer I have come to a general solution. I think filtering by a list of ids is a very common task and therefore should be included in the FilterBackend:

class ListFilter(django_filters.Filter):

    """Class to filter from list of integers."""

    def filter(self, qs, value):
        """Filter function."""
        if not value:
            return qs
        self.lookup_type = 'in'
        try:
            map(int, value.split(','))
            return super(ListFilter, self).filter(qs, value.split(','))
        except ValueError:
            return super(ListFilter, self).filter(qs, [None])


class FilterBackend(filters.DjangoFilterBackend):

    """A filter backend that includes ListFilter."""

    def get_filter_class(self, view, queryset=None):
        """Append ListFilter to AutoFilterSet."""
        filter_fields = getattr(view, 'filter_fields', None)

        if filter_fields:
            class AutoFilterSet(self.default_filter_set):
                ids = ListFilter(name='id')

                class Meta:
                    model = queryset.model
                    fields = list(filter_fields) + ["ids"]

            return AutoFilterSet

        else:
            return super(FilterBackend, self).get_filter_class(view, queryset)

Uptodate solution:

from django_filters import rest_framework as filters

name-->field_name

lookup_type-->lookup_expr

class IntegerListFilter(filters.Filter):
    def filter(self,qs,value):
        if value not in (None,''):
            integers = [int(v) for v in value.split(',')]
            return qs.filter(**{'%s__%s'%(self.field_name, self.lookup_expr):integers})
        return qs

class MyFilter(filters.FilterSet):   
    ids = IntegerListFilter(field_name='id',lookup_expr='in')
    class Meta:
        model = MyModel
        fields = ('ids',)

class MyModelViewSet(viewsets.ModelViewSet):
    queryset = MyModel.objects.all()
    serializer_class = MyModelSerializer
    filter_class = MyFilter

As I have answered here DjangoFilterBackend with multiple ids, it is now pretty easy to make a filter that accepts list and validates the contents

For Example:


from django_filters import rest_framework as filters


class NumberInFilter(filters.BaseInFilter, filters.NumberFilter):
    pass

class MyFilter(filters.FilterSet):
    id_in = NumberInFilter(field_name='id', lookup_expr='in')

    class Meta:
        model = MyModel
        fields = ['id_in', ]

This will accept a list of integers from a get parameter. For example /endpoint/?id_in=1,2,3

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top