Joey van Breukelen
Joey van Breukelen

Reputation: 245

use django_filters to filter for multiple arguments

I am using Relay, Django, Graphene Graphql.

I would like to use django_filters to filter for multiple arguments of type on accommodation. This is described in my schema file and atm looks like:

class AccommodationNode(DjangoObjectType) :
    class Meta:
        model = Accommodation
        interfaces = (relay.Node,)
        filter_fields = ['type']

This works perfectly if I pass a single string like: {"accommodationType": "apartment"}, but what if I want to filter for all accommodations that are apartments OR hotels? something like: {"accommodationType": ["apartment","hotel"]}

This is my model:

class Accommodation(models.Model):
    ACCOMMODATION_TYPE_CHOICES = (
        ('apartment', 'Apartment'),
        ('host_family', 'Host Family'),
        ('residence', 'Residence'),
    )
    school = models.ForeignKey(School, on_delete=models.CASCADE, related_name='accommodations')
    type = models.CharField(
        max_length=200,
        choices=ACCOMMODATION_TYPE_CHOICES,
        default='apartment'
    )
    def __str__(self):
        return str(self.school) + " - " + self.type

Is there any way I can do this without writing custom filters as are suggested here? For only one filter field this is a great solution but I'll end up having around 50 throughout my application including linked objects...

Upvotes: 1

Views: 3110

Answers (2)

Joey van Breukelen
Joey van Breukelen

Reputation: 245

like FlipperPA mentioned, I need to use 'in'. According to the django_filter docs:

‘in’ lookups return a filter derived from the CSV-based BaseInFilter.

and an example of BaseInFilter in the docs:

class NumberRangeFilter(BaseInFilter, NumberFilter):
    pass

class F(FilterSet):
    id__range = NumberRangeFilter(name='id', lookup_expr='range')

    class Meta:
        model = User

User.objects.create(username='alex')
User.objects.create(username='jacob')
User.objects.create(username='aaron')
User.objects.create(username='carl')

# Range: User with IDs between 1 and 3.
f = F({'id__range': '1,3'})
assert len(f.qs) == 3

The answer to my question:

class AccommodationNode(DjangoObjectType) :
    class Meta:
        model = Accommodation
        interfaces = (relay.Node,)
        filter_fields = {
            'type': ['in']
            }

With the argument {"accommodationType": "apartment,hotel"} will work

Upvotes: 2

FlipperPA
FlipperPA

Reputation: 14311

Have a look at Django REST Framework Filters:

https://github.com/philipn/django-rest-framework-filters

It supports more than exact matches, like in, which you are looking for, but also exact, startswith, and many more, in the same style of Django's ORM. I use it frequently and have been impressed - it even integrates with DRF's web browseable API. Good luck!

Upvotes: 2

Related Questions