Search code examples
pythondjangodjango-querysetdjango-filter

How can I achieve filtering with multiple values for the same parameter in Django?


I am building a Django website that displays snowboards that will fit you based on some parameters. One of the parameters is gender and for example if the user specifies she is a girl, then I want to display Female as well as Unisex boards - and also then filter again by all the other parameters (height, style, level, etc). Same for the boys. I want to also display Male boards as well as Unisex boards.

This is the code snippet in my TemplateView:

    def get(self, request, *arg, **kwargs):
        gender = request.GET.get('gender')
        skills = request.GET.get('skills')
        style = request.GET.get('style')
        rider_name = request.GET.get('rider_name').split("'")[1].split("'")[0]
        filter = process_queryset(gender, skills, style)
        queryset = Snowboard.objects.filter(
            gender=filter['gender'],
            style=filter['style'],
            level=filter['level'],
        )
        return render(request, self.template_name,
                      {'gender': gender, 'snowboards': queryset, 'rider_name': rider_name})

and I have this separate function for processing the filtering:

def process_queryset(gender, skills, style):
    filter_dict = {'gender': 'Female' if gender == 'girl' else 'Male',
                   'level': 'Beginner' if 'rookie' in skills else 'Intermediate-Advanced'}
    if style == 'freestyle':
        filter_dict['style'] = 'Park'
    elif style == 'freeride':
        filter_dict['style'] = 'Free Ride'
    else:
        filter_dict['style'] = 'All mountain'
    return filter_dict

So I first tried to filter by the gender and have them both (tried both with | and with &) and then nest the QuerySet with the other filter

queryset = gender_filtering.filter(
            style=filter['style'],
            level=filter['level'],
        )
        queryset = Snowboard.objects.filter(
            gender=filter['gender'],
            style=filter['style'],
            level=filter['level'],
        )```

Also tried a lot of other stuff but none of it worked.

Solution

  • When you unite 2 querysets with and without filter you can see that filter doesn't work at all. You want to filter snowboards where gender is user's or unisex. That is simple as that:

    queryset = Snowboard.objects.filter(
                   gender__in=[filter['gender'], 'unisex'], 
                   ...your other filters
                   )
    
    

    I am using in lookup to filter all snowboards by their gender and it will return you a queryset with both male or female and unisex snowboards. You can find more details how it works and learn more about field lookups in documentation