Using jQuery autocomplete with Flask

2020-02-26 03:32发布

问题:

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?

回答1:

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.



回答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>