3

I have set up the column where one of the table is called Establishment_Type

Now, I am trying to filter according to Establishment_Type.

Here is my view.py code

class ShopDetailAPIView(ListAPIView):
    serializer_class = ShopDetailSerializer
    def get_queryset(self):
        queryset = Shop.objects.all()
        type = self.request.query_params.get('type', None)
        type2 = self.request.query_params.get('type2', None)
        if type is not None and type2 is None:
            queryset = queryset.filter(Establishment_Type = type)
        elif type is not None and type2 is not None:
            queryset = queryset.filter(Q(Establishment_Type = type) | Q(Establishment_Type = type2))
        return queryset

In the url, I query by typing:

http://127.0.0.1:8000/shop/search/?type=Restaurant&type2=Petrol%20Station

Which only filter Establishment_Type = Restaurant but not include Establishment_Type = Petrol Station

Here is my urls.py within my app called shop:

urlpatterns = [

    url(r'^$', ShopListAPIView.as_view(), name = 'list' ),
    #####
    url(r'^create/$', ShopCreateAPIView.as_view(), name = 'create' ),
    url(r'^search/$', ShopDetailAPIView.as_view(), name = 'detail'),
]

Was my url for filtering 2 Establishment type wrong?

Do I need to change something in my code in order to filter 2 values in column Establishment_Type?

4
  • Your URL makes no sense. You haven't even included type2. Commented Mar 30, 2017 at 8:08
  • forget to add that in when i type. i have added type2 in the url and it doesn't work as well. Commented Mar 30, 2017 at 8:09
  • I think you want queryset.filter(Establishment_Type__in=types), where types is list of your not None types. Commented Mar 30, 2017 at 8:14
  • BTW instead of .get('key', None) use just .get('key'). It's the same. Commented Mar 30, 2017 at 8:15

2 Answers 2

1

Thanks @Thyrst' for advising me to use Establishment_Type__in=types

I have modify my code this way for my filter to work

class ShopDetailAPIView(ListAPIView):
    serializer_class = ShopDetailSerializer
    def get_queryset(self):
        queryset = Shop.objects.all()
        type = self.request.query_params.get('type', None)
        type = type.split(',')
        if type is not None:
            queryset = queryset.filter(Establishment_Type__in = type)
        return queryset

so type is now list, therefore when entered the url:

http://127.0.0.1:8000/shop/search/?type=Restaurant,Petrol%20Station

it filters according to Restaurant and Petrol Station.

it also works when entering just 1 value or more.

This is good for now but I feel like there might be a better way to implement this.

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

Comments

0

There is an even simpler way to achieve this using the django-filter package. Deep within the django-filter documentation, it mentions that you can use "a dictionary of field names mapped to a list of lookups".

Your code would be updated like so:

# views.py

from django_filters.rest_framework import DjangoFilterBackend

class ShopDetailAPIView(ListAPIView):
    queryset = Shop.objects.all()
    serializer_class = ShopDetailSerializer
    filter_backends = [DjangoFilterBackend]
    filter_fields = {
        'type': ["in", "exact"]
    }

Now in the URL you would add __in to the filter before supplying your list of parameters and it would work as you expect:

http://127.0.0.1:8000/shop/search/?type__in=Restaurant,Petrol%20Station

The django-filter documentation on what lookup filters are available is quite poor, but the in lookup filter is mentioned in the Django documentation itself.

Comments

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.