Django QuerySet API: How do I join iexact and icontains?

情到浓时终转凉″ 提交于 2019-12-11 04:17:36

问题


I have this join:

lawyers = Lawyer.objects.filter(last__iexact=last_name).filter(first__icontains=first_name)

This is the site

If you try Last Name: Abbas and First Name: Amr it tells you that amr abbas has 1 schoolmates.

But if you try First name only it says that there are no lawyers in the database called amr (obviously there is).

If I change (last__iexact=last_name) to (last__icontains=last_name) then leaving Last Name blank works fine and amr is found.

But with last__icontains=last_name if you search for "collin" you also get "collins" and "collingwood" which is not what I want.

Do you know how I can use iexact and also have it ignored if it is blank?

Thanks

This is the view function:

def search_form(request):
    if request.method == 'POST':
        search_form = SearchForm(request.POST)
        if search_form.is_valid():
            last_name = search_form.cleaned_data['last_name']
            first_name = search_form.cleaned_data['first_name']
            lawyers = Lawyer.objects.filter(last__iexact=last_name).filter(first__icontains=first_name)
            if len(lawyers)==0:
                form = SearchForm()
                return render_to_response('not_in_database.html', {'last': last_name, 'first': first_name, 'form': form})
            if len(lawyers)>1:
                form = SearchForm(initial={'last_name': last_name})
                return render_to_response('more_than_1_match.html', {'lawyers': lawyers, 'last': last_name, 'first': first_name, 'form': form}) 
            q_school = Lawyer.objects.filter(last__icontains=last_name).filter(first__icontains=first_name).values_list('school', flat=True)
            q_year = Lawyer.objects.filter(last__icontains=last_name).filter(first__icontains=first_name).values_list('year_graduated', flat=True)
            lawyers1 = Lawyer.objects.filter(school__iexact=q_school[0]).filter(year_graduated__icontains=q_year[0]).exclude(last__icontains=last_name)
            form = SearchForm()
            return render_to_response('search_results.html', {'lawyers': lawyers1, 'last': last_name, 'first': first_name, 'form': form})
    else:
        form = SearchForm()
        return render_to_response('search_form.html', {'form': form, })

回答1:


You don't have to build the QuerySet all in one go.

lawyers = Lawyer.objects.all()
if last_name:
    lawyers = lawyers.filter(last__iexact=last_name)
if first_name:
    lawyers = lawyers.filter(first__icontains=first_name)

Django won't evaluate the QuerySet until it needs to (in this case, the len() call forces it to evaluate), so you can keep stacking filters on all days long until you're ready to run the query.

http://docs.djangoproject.com/en/dev/ref/models/querysets/#when-querysets-are-evaluated

Additionally, you don't need to create new QuerySets later on, you can just use the existing one.

q_school = Lawyer.objects.filter(last__icontains=last_name).filter(first__icontains=first_name).values_list('school', flat=True)
q_year = Lawyer.objects.filter(last__icontains=last_name).filter(first__icontains=first_name).values_list('year_graduated', flat=True)

Can be:

q_school = lawyers.values_list('school', flat=True)
q_year = lawyers.values_list('year_graduated', flat=True)


来源:https://stackoverflow.com/questions/2103507/django-queryset-api-how-do-i-join-iexact-and-icontains

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!