1

I am working with django-rest-framework and I have an API that returns me the info with a filter like this:

http://example.com/api/products?category=clothing&in_stock=True
--this returns me 10 items

But it also returns the whole Model data if I dont put the filters, this is the default way.

http://example.com/api/products/
--this returns me more than 100 (all the Model Table)

How can I disable this default operation, I mean, how can I make a filter to be necesary to make this api works? or even better! how can I make the last URL to return an empty json response?

UPDATE Here is some code:

serializers.py

class OEntradaDetalleSerializer(serializers.HyperlinkedModelSerializer):
    item = serializers.RelatedField(source='producto.item')
    descripcion = serializers.RelatedField(source='producto.descripcion')
    unidad = serializers.RelatedField(source='producto.unidad')
    class Meta:
        model = OEntradaDetalle
        fields = ('url','item','descripcion','unidad','cantidad_ordenada','cantidad_recibida','epc')

views.py

class OEntradaDetalleViewSet(BulkUpdateModelMixin,viewsets.ModelViewSet):
    filter_backends = (filters.DjangoFilterBackend,)
    filter_fields = ('cantidad_ordenada','cantidad_recibida','oentrada__codigo_proveedor','oentrada__folio')
    queryset = OEntradaDetalle.objects.all()
    serializer_class = OEntradaDetalleSerializer

urls.py

router2 = BulkUpdateRouter()
router2.register(r'oentradadetalle', OEntradaDetalleViewSet)

urlpatterns = patterns('',
url(r'^api/',include(router2.urls)),
)

URL EXAMPLE

http://localhost:8000/api/oentradadetalle/?oentrada__folio=E01
THIS RETURNS ONLY SOME FILTERED VALUES

http://localhost:8000/api/oentradadetalle/
THIS RETURNS EVERYTHING IN THE MODEL (I need to remove this or make it return some empty data)
2
  • please give some code. Commented Oct 30, 2014 at 21:43
  • I dont know why do you need some code, it has the default API behavior, and I need to override it. Anyway... there's an Update with my own code, I hope you can help me. Thanks Commented Oct 30, 2014 at 22:28

1 Answer 1

3

I would highly recommend using pagination, to prevent anyone from being able to return all of the results (which likely takes a while).

If you can spare the extra queries being made, you can always check if the filtered and unfiltered querysets match, and just return an empty queryset if that is the case. This would be done in the filter_queryset method on your view.

def filter_queryset(self, queryset):
    filtered_queryset = super(ViewSet, self).filter_queryset(queryset)

    if queryset.count() === len(filtered_queryset):
        return queryset.model.objects.none()

    return filtered_queryset

This will make one additional query for the count of the original queryset, and if it is the same as the filtered queryset, an empty queryset will be returned. If the queryset was actually filtered, it will be returned and the results will be what you are expecting.

Sign up to request clarification or add additional context in comments.

2 Comments

This is exactly what I needed!! You are superb @Kevin Brown. Thank you so much!
I have a strange situation here... this works with two or more objects in the filter, I mean, I am filtering by oentrada__folio field, but if I have only one, this doesn't work because the queryset is always equals to the filtered_queryset, how can I make this thing works with one entry? I can make a query to count the ocompra__folio's qty and IF it is 1, then returns me the queryset, but is there another method that dont make another query?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.