with sort modelviewset framework filterset filters python django api rest django-rest-framework

python - sort - Django REST framework-filtrado contra param de consulta



filter serializer django (3)

Así que creé mi "API" usando el marco REST, ahora tratando de filtrarlo. Así es como se ven mis models.py más o menos:

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)

Así que me gustaría ver en mi archivo JSON "todos los pasajeros en un área de trabajo particular" o "todos los pasajeros en una aerolínea particular", etc.

Aquí está mi, 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

Y 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

Es la primera vez que utilizo el marco REST, he comprobado los documentos, me han ayudado con lo que he hecho hasta ahora, me gustaría usar

Filtrado según el parámetro de consulta: http://www.django-rest-framework.org/api-guide/filtering/#filtering-against-query-parameters

Realmente no puedo conseguirlo ...


Así que con @limelights logré hacer lo que quería, aquí está el código:

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


Esta github.com/manjitkumar/drf-url-filters aplica filtros en el conjunto de consultas de una vista usando los parámetros de consulta entrantes de una manera limpia y elegante.

Que se puede instalar con pip como pip install drf-url-filters

Ejemplo de uso

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(), } )

vistas.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)


Puede obtener la misma funcionalidad fuera de la caja simplemente usando el paquete django-filter como se indica en los documentos 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'')

En este caso, tendrá que realizar el filtrado utilizando ''workspace = 1'' o ''workspace__airline = 1''