3

This question has been asked before, and I think I've done what I've seen there, but I don't really know what I'm doing wrong. I don't know a lot about jQuery, but I'll do my best to explain what I'm trying to do.

I want to autocomplete based on a query from a database, so I have this in my template:

<script type="text/javascript">
    $(function() {
        $( "#function_name" ).autocomplete({
            source: '{{url_for("autocomplete")}}',
            minLength: 2,
        });
    });
</script>

<form id="function_search_form" method="post" action="">
    {{form.function_name}}
</form>

The form is generated by this Flask form class:

class SearchForm(Form):
    function_name = TextField('function_name', validators = [Required()])

And here is the autocomplete function:

@app.route('/autocomplete')
def autocomplete():
    results = []
    search = request.args.get('term')
    results.append(db.session.query(Table.Name).filter(Table.Name.like('%' + search + '%')).all())
    return dumps(results)

So the jQuery should go to the autocomplete function and get some JSON back to autocomplete with. At least I think that's what's going on. What am I doing wrong here?

2
  • @morphyn Yeah. It's called function_name. I even checked the HTML generated by Flask and it's correct. EDIT: It seems that comment has disappeared. Oh well.
    – miscsubbin
    Commented Jun 28, 2013 at 13:44
  • Hi miscsubbin, I am trying implement this autocomplete feature but I am not able to do so. I tried your method as well and tried the solution provided below. but I am facing problem in getting value in request.args.get('term'). Its always null for me. Dont know whats happening. It would be great if you can provide your working code snippet. Thanks in advance.
    – Pradeepb
    Commented Dec 30, 2015 at 20:08

2 Answers 2

3

Update:

autocomplete doesn't handle the Ajax request automatically if you give it a URL, you must do it manually:

$(document).ready(function() {
    $.ajax({
        url: '{{ url_for("autocomplete") }}'
    }).done(function (data) {
        $('#function_name').autocomplete({
            source: data,
            minLength: 2
        });
    });
}

You might have to modify the way you handle the returned data, depending on what your API returns.

Update 2:

The result of your query on the server side looks like this:

[[["string1"], ["string2"], ... ["stringn"]]]

You can flatten it before sending it:

import itertools
flattened = list(itertools.chain.from_iterable(result[0]))

But you could probably improve your query to return a list of strings directly. You will need to post the whole code if you want help with that.

7
  • The autocomplete function actually works fine. If I go to 127.0.0.1:5000/autocomplete?term=something, I will receive the appropriate JSON. My table is called something else, but for the purpose of the question, it's not really needed. Also, the reason I used results.append and results = [], is that I use a slightly more complex query that involves a loop, but that's not the problem I'm having.
    – miscsubbin
    Commented Jun 28, 2013 at 13:58
  • OK, my next guess is that you probably cannot give the URL directly in the source parameter of the autocomplete function. You probably have to do the Ajax request manually. I will update my answer to give an example. Commented Jun 28, 2013 at 14:09
  • So it's currently actually GET'ing from my function. I've changed my function a bit to just return every name in JSON. I'm still not getting any autocomplete though. Is there a way I should format the response made by Flask? How should I go about doing that?
    – miscsubbin
    Commented Jun 28, 2013 at 14:47
  • Did you use my code ? If yes, could you try to console.debug(data) in the handling js function to see what the JSON looks like ? I think autocomplete just wants a list (array) of strings. Commented Jun 28, 2013 at 14:55
  • Hmm, data is of the form [[["string1"], ["string2"], ... ["stringn"]]] which I am assuming is the incorrect type. What would be a good way to format this correctly?
    – miscsubbin
    Commented Jun 28, 2013 at 15:27
2

You actually don't even need a request to make this work! Using standard jquery-ui autocomplete, you can throw your possible items into a jinja variable and then:

<script type="text/javascript">
$('#search_form').autocomplete({
    source: JSON.parse('{{jinja_list_of_strings | tojson | safe}}'),
    minLength: 2,
    delay: 10,
});
</script>

This is really handy if the items are tied to current_user, as in Flask-Login.

<script type="text/javascript">
$('#search_form').autocomplete({
    source: JSON.parse('{{current_user.friends | map(attribute="name") | list | tojson | safe}}'),
    minLength: 2,
    delay: 10,
});
</script>

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.