0

I have made a successful AJAX search box, but being fairly new, I was wondering if there was a better way to write this code. I am using Python 3.6 and Django 2. Also, I want to display all entries on page load, which currently displays nothing. If I enter text and delete it, then all my entries show, but not on initial load. Thanks!

views.py

    def search_ajax(request):

        if request.method == 'POST':
            search_text = request.POST['search_text']
            if ',' in search_text:
                last,first = search_text.split(",")
                name_search = PhoneBook.objects.filter(last_name__istartswith=last.strip()
            ).filter(first_name__istartswith=first.strip())
            else:
                name_search = PhoneBook.objects.filter(last_name__istartswith=search_text.strip())

            phone_search = search = PhoneBook.objects.filter(number__icontains=search_text.strip())
            if search_text != "":
                search = list(chain(name_search, phone_search))[:10]
            else:
                search = list(chain(name_search, phone_search))
            print(search)
            context={'search':search,}
            html = render_to_string('search_ajax_results.html', context)
            return HttpResponse(html, content_type="application/json")

ajax_script.js

    $(function(){

        $('#search_ajax_input').keyup(function(){
        $.ajax({
            type:"POST",
            url:"search-ajax/",
            data:{
                'search_text': $('#search_ajax_input').val(),
                'csrfmiddlewaretoken' : $("input[name=csrfmiddlewaretoken]").val()
            },
            success: searchSuccess,
            dataType: 'html'
        });
        });
    });

    function searchSuccess(data, textStatus,jqXHR)
    {
        $('#search-ajax-results').html(data);
    };
Carl Brubaker
  • 1,602
  • 11
  • 26
  • I think the missing part is to run search function on page load: [Make jquery function run on page load](https://stackoverflow.com/questions/12468374/make-jquery-function-run-on-page-load). You may want to tag jquery so the people can provide answer. – Hai Lang Mar 30 '18 at 14:48

1 Answers1

1

Display all entries on page load

Put the ajax call in a separate function and call it on keyup as well as on page load

ajax_script.js

$(function() {
    // perform search on page load
    search();
    $('#search_ajax_input').keyup(search);
});

function searchSuccess(data, textStatus, jqXHR) {
    $('#search-ajax-results').html(data);
};

function search() {
    $.ajax({
        type: "POST",
        url: "search-ajax/",
        data: {
            'search_text': $('#search_ajax_input').val(),
            'csrfmiddlewaretoken': $("input[name=csrfmiddlewaretoken]").val()
        },
        success: searchSuccess,
        dataType: 'html'
    });
}

Better server side code

This is not an extensive list, rather a few points to make your view more pythonic/less error prone

  • Check for request.POST directly if request.method == 'POST': becomes if request.POST:
  • To access dictionary values, use the get function to avoid KeyError search_text = request.POST['search_text'] becomes search_text = request.POST.get('search_text')
  • Follow PEP 8 style guide e.g. Use either single or double quotations for your strings but be consistent about it, use a space after ,, surround = with spaces when assigning variables but not when passing function kwargs, etc.
  • To enhance code readability, use a positive check for the if condition if search_text != "": becomes if search_text == "": and switch the then and else blocks
  • Python automatically evaluates empty string/zero/empty array/etc. to False meaning if search_text: is equivalent to if search_text != "":
  • The variable search is set to either list(chain(name_search, phone_search)) or list(chain(name_search, phone_search))[:10] depending on the if condition, so why do you give it a value in phone_search = search = PhoneBook.objects.filter(number__icontains=search_text.strip()) before the if condition when you are going to overwrite it anyways?
  • It would make slightly more sense in the template to use the name results or search_results to represent the results, just search can be slightly confusing.
Nader Alexan
  • 2,127
  • 22
  • 36