En este snippet pretendemos hacer varios filtros diferentes para una aplicación django que usa django rest framework (DRF).
No se cubre la instalación, configuración y puesta en marcha de django filters. Aquí tienes varios enlaces con información relevante:
Filtrado DRF Integración DRF django filter github
IMPORTANTE: Los filtros necesitan de un serializer + viewset que creamos con DRF.
Este es el ejemplo más común. Con agregar unos pocos parámetros tenemos hecho el filtrado. Documentación oficial.
class ProductList(generics.ListAPIView):
permission_classes = (permissions.IsAuthenticated,)
queryset = Access.objects.all()
serializer_class = AccessSerializer
filter_fields = ('category', 'in_stock')
En el ejemplo, agregamos un permiso para exigir login al usar la API. Además:
-
Con el
query_set
obtenemos los datos que se van a mostrar, en el ejemplo, todos. -
Por su lado,
serializer_class
hace referencia al serializer encargado de determinar que campos se podrán consultar. -
Por último, lo que nos interesa en este ejemplo, el
filter_fields
que se emplea para realizar el filtrado de campos, por ejemplo, con un string indicando la categoria por la que filtrar los resultados.
¿Qué pasa si queremos filtrar por fechas?
Es bastante improbable que queramos una fecha y horas específicias,
menos aún el el formato que nos muestra django, algo como esto:
2018-04-02T16:09:09.949331Z
. Lo lógico sería filtrar si contiene
la fecha o está en un rango mayor o menor a una fecha dada.
Ideal para devolver los resultados de, por ejemplo, un día concreto. En el ejemplo usaremos un campo datetime en el modelo pero filtraremos por un date para obtener el día.
class ProductListDayDateFilter(filters.FilterSet):
# Hacemos filtrado por fecha
last_update_contains = django_filters.DateFilter(name="last_update", lookup_expr='contains')
class Meta:
model = ProductList
# Especificamos el nombre del campo filtro
fields = ['last_update_contains']
class ProductListViewSet(viewsets.ModelViewSet):
permission_classes = (permissions.IsAuthenticated,)
queryset = ProductList.objects.all()
serializer_class = ProductListSerializer
filter_backends = (filters.DjangoFilterBackend,)
# Especificamos el filtro que se va a emplear
filter_class = ProductListDayDateFilter
Ideal para devolver los resultados de, por ejemplo, una semana. Dependiendo de como lo usemos también vale para consultar el día pero es mucho menos intuitivo que la opción de Contiene la fecha.
class ProductListDateLteGteFilter(filters.FilterSet):
# Filtra por las fechas inferiores a la introducida
last_update_lte = django_filters.DateTimeFilter(name="last_update", lookup_expr='lte')
# Filtra por las fechas mayores a la introducida
last_update_gte = django_filters.DateTimeFilter(name="last_update", lookup_expr='gte')
class Meta:
model = ProductListnswer
# Especificamos el nombre de los campos filtro
fields = ['last_update_gte', 'last_update_lte']
class ProductListViewSet(viewsets.ModelViewSet):
permission_classes = (permissions.IsAuthenticated,)
queryset = ProductList.objects.all()
serializer_class = ProductListSerializer
filter_backends = (filters.DjangoFilterBackend,)
# Especificamos el filtro que se va a emplear
filter_class = ProductListDateLteGteFilter