Emile
Emile

Reputation: 3484

Django: get_queryset method for a Search View to filter with multiple fields

I am working on an HTML form to filter multiple model fields.

Question:

How to build the view so a single queryset is returned even with changing queries?

HTML

My form will pass the inputs as kwargs so request will be like this -

/search/?order_by=newest
/search/?q=<string>&order_by=newest
/search/?q=<string>&order_by=newest&country=US

These would filter upon:

View:

I'm trying to have a single query in the view to remove complexity and keep the view as simple as possible. How can I take all of these potential variations and pass through a single get_queryset method?

Here is what I have right now.

def get_queryset(self):
    keywords = self.request.GET.get('q') or None
    order_by = self.order_by_options.get(
        self.request.GET.get('order_by')) or '-date_of_price'
    if keywords:
        query = SearchQuery(keywords)
        vectors = SearchVector('name', weight='A')
        qs = self.model.objects_for_search.annotate(search=vectors).filter(
            search=query).order_by('sold', order_by, '-modified')
    else:
        qs = self.model.objects_for_search.order_by('sold', order_by, '-modified')
    return qs[0:500]

The issue with the code above is that the more attributes I add, the more if statements. This code has the if statement for keywords, and that doesn't feel elegant/pythonic to me. Adding another if statement for the country query would definitely be odd.

Upvotes: 1

Views: 1287

Answers (1)

Pushplata
Pushplata

Reputation: 582

kwargs = {
    'q': request.GET.get('q',''),
    'order_by_field': request.GET.get('order_by','-date_of_price'),
    'country': request.GET.get('country','-date_of_price')
}

Get all query parameter and make a kwargs with these. we don't have options other than if else. For eg -

    filter_kwargs = {}
    if 'q' in kwargs and kwargs['q']:
        filter_kwargs['keyword'] = kwargs['q']
    if 'country' in kwargs and kwargs['country']:
        filter_kwargs['country'] = kwargs['country']

    result = self.query.objects.filter(**filter_kwargs) \
             .order_by(kwargs['order_by_field'])

Upvotes: 1

Related Questions