A
A
AntonIgin2017-07-01 21:50:13
Django
AntonIgin, 2017-07-01 21:50:13

How to search for object instances by empty fields?

I have a form that has several optional filters: age, eye color, zodiac sign, and so on. If the user did not specify all this, there will be no filtering by the specified parameter.
And here is the problem: these fields are optional not only for the search form, but also for the registration form, that is, questionnaires with empty values ​​are possible.
To filter by age, I did this (I know that it is necessary to classify, but I will rewrite later):

def new_services_search(request, name='', ages=['18_24', '24_35', '36_42', '43+', None]):
    if request.method=='POST':
        data = request.POST
        name = data.get('name')
        if data.get('age'):
            age = list(data.getlist('age'))
        filter_girls = Profile.objects.filter(available=True, name__istartswith=name,age__in=ages)

I think the point is clear. If the user has specified the ranges of the required ages, then we filter by them, if not, we filter by the list from the function header. But questionnaires with empty values ​​do not pass, although there is None in the list, and checking the problematic profile in the shell with a command like test.age==None showed that it was True. But in the view it becomes "not true".
What to do?

Answer the question

In order to leave comments, you need to log in

1 answer(s)
S
Sergey Gornostaev, 2017-07-01
@AntonIgin

The code is a rough sketch and needs some tweaking, but what you want is something like, as far as I understand it:

from django.db.models import Q

# Это лучше хранить где-нибудь в базе, а не в коде
DEFAULTS = {
    'name': '',
    'age': ['18_24', '24_35', '36_42', '43+', None],
    'eye': None,
}

def new_services_search(request):
    if request.method=='POST':
        filters = []
        for k in request.POST:
            kwargs = {}
            v = request.POST.get(k, DEFAULTS[k])
            if v is None:
                kwargs[k + '__isnull'] = True
            elif isinstance(v, list):
                kwargs[k + '__in'] = v
            else:
                kwargs[k] = v
            filters.append(Q(**kwargs))
        filter_girls = Profile.objects.filter(filters)

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question