web-dev-qa-db-fra.com

Django REST - filtrage par paramètre de requête)

J'ai donc créé mon "API" en utilisant REST, essayant maintenant de filtrer pour cela. C'est ainsi que mon models.py ressemble plus ou moins à:

class Airline(models.Model):
    name = models.TextField()

class Workspace(models.Model):
    airline = models.ForeignKey(Airline)
    name = models.CharField(max_length=100)

class Passenger(models.Model):
    workspace = models.ForeignKey(Workspace)
    title = models.CharField(max_length=200)

Je voudrais donc voir dans mon fichier JSON "tous les passagers dans un espace de travail particulier" ou "tous les passagers dans une compagnie aérienne", etc.

Voici mon, serializers.py

class AirlineSerializer(serializers.ModelSerializer):
    class Meta:
        model = Airline


class WorkspaceSerializer(serializers.ModelSerializer):
    class Meta:
        model = Workspace


class PassengerSerializer(serializers.ModelSerializer):
    class Meta:
        model = Passenger

Et views.py:

class AirlineList(generics.ListCreateAPIView):
    model = Airline
    serializer_class = AirlineSerializer


class AirlineDetail(generics.RetrieveUpdateDestroyAPIView):
    model = Airline
    serializer_class = AirlineSerializer


class WorkspaceList(generics.ListCreateAPIView):
    model = Workspace
    serializer_class = WorkspaceSerializer


class WorkspaceDetail(generics.RetrieveUpdateDestroyAPIView):
    model = Workspace
    serializer_class = WorkspaceSerializer


class PassengerList(generics.ListCreateAPIView):
    model = Passenger
    serializer_class = PassengerSerializer


class PassengerDetail(generics.RetrieveUpdateDestroyAPIView):
    model = Passenger
    serializer_class = PassengerSerializer

C'est la première fois que j'utilise REST, j'ai vérifié les documents, ils m'ont aidé avec ce que j'ai fait jusqu'à présent, je voudrais utiliser

Filtrage par paramètre de requête: http://www.Django-rest-framework.org/api-guide/filtering/#filtering-against-query-parameters

Je ne peux pas vraiment l'obtenir ..

29
knowbody

Donc avec les @limelights j'ai réussi à faire ce que je voulais, voici le code:

class PassengerList(generics.ListCreateAPIView):
    model = Passenger
    serializer_class = PassengerSerializer

    # Show all of the PASSENGERS in particular WORKSPACE
    # or all of the PASSENGERS in particular AIRLINE
    def get_queryset(self):
        queryset = Passenger.objects.all()
        workspace = self.request.query_params.get('workspace')
        airline = self.request.query_params.get('airline')

        if workspace:
            queryset = queryset.filter(workspace_id=workspace)
        Elif airline:
            queryset = queryset.filter(workspace__airline_id=airline)

        return queryset
43
knowbody

Vous pouvez obtenir la même fonctionnalité hors de la boîte en utilisant simplement le package de filtre Django comme indiqué dans les documents http://www.Django-rest-framework.org/api-guide/filtering/#djangofilterbackend =

from rest_framework import filters 

class PassengerList(generics.ListCreateAPIView):
    model = Passenger
    serializer_class = PassengerSerializer
    queryset = Passenger.objects.all()
    filter_backends = (filters.DjangoFilterBackend,)
    filter_fields = ('workspace', 'workspace__airline')

Dans ce cas, vous devrez effectuer un filtrage en utilisant 'workspace = 1' ou 'workspace__airline = 1'

9
Gabriel Muj

Cette application Django applique des filtres sur l'ensemble de requêtes d'une vue en utilisant les paramètres de requête entrants de manière claire et élégante.

Qui peut être installé avec pip comme pip install drf-url-filters

Exemple d'utilisation

validations.py

from filters.schema import base_query_param_schema
from filters.validations import (
    CSVofIntegers,
    IntegerLike,
    DatetimeWithTZ
)

# make a validation schema for players filter query params
players_query_schema = base_query_param_schema.extend(
    {
        "id": IntegerLike(),
        "name": unicode,
        "team_id": CSVofIntegers(),  # /?team_id=1,2,3
        "install_ts": DatetimeWithTZ(),
        "update_ts": DatetimeWithTZ(),
    }
)

views.py

from rest_framework import (
    viewsets,
    filters,
)

from .models import Player, Team
from .serializers import PlayerSerializer, TeamSerializer
from .pagination import ResultSetPagination
from .validations import teams_query_schema, players_query_schema
from filters.mixins import (
    FiltersMixin,
)


class PlayersViewSet(FiltersMixin, viewsets.ModelViewSet):
    """
    This viewset automatically provides `list`, `create`, `retrieve`,
    `update` and `destroy` actions.
    """
    serializer_class = PlayerSerializer
    pagination_class = ResultSetPagination
    filter_backends = (filters.OrderingFilter,)
    ordering_fields = ('id', 'name', 'update_ts')
    ordering = ('id',)

    # add a mapping of query_params to db_columns(queries)
    filter_mappings = {
        'id': 'id',
        'name': 'name__icontains',
        'team_id': 'teams',   # many-to-many relationship
        'install_ts': 'install_ts',
        'update_ts': 'update_ts',
        'update_ts__gte': 'update_ts__gte',
        'update_ts__lte': 'update_ts__lte',
    }

    # add validation on filters
    filter_validation_schema = players_query_schema

    def get_queryset(self):
        """
        Optionally restricts the queryset by filtering against
        query parameters in the URL.
        """
        query_params = self.request.query_params
        queryset = Player.objects.prefetch_related(
            'teams'  # use prefetch_related to minimize db hits.
        ).all()

        # This dict will hold filter kwargs to pass in to Django ORM calls.
        db_filters = {}

        # update filters dict with incoming query params and then pass as
        # **kwargs to queryset.filter()
         db_filters.update(
            self.get_queryset_filters(
                query_params
            )
        )
        return queryset.filter(**db_filters)
5
Manjit Kumar