Reputation: 847
After some extensive research (Googling), I cannot find a current tutorial on how to set up autocomplete using Django and jQuery. There appears to be a variety of plugins and there appears to be no consistency or standard about which to use or when.
I'm not a pro at either Django or jQuery, but need an autocomplete solution that is well documented and fairly simple to utilize.
Suggestions?
Upvotes: 26
Views: 35445
Reputation: 2272
Let's say you want to set up autocomplete on some input field (like <input type="text" id="id_input">
) with the username of your users. This is the way I did it:
urls.py
First of all, add a url that will be used by the AJAX call.
url(r'^ajax/autocomplete/$', views.autocomplete, name='ajax_autocomplete')
views.py
Then set a view to retrieve the information (i.e the usernames, in this case) from the database
from django.http import JsonResponse
def autocomplete(request):
if request.is_ajax():
username_query = request.GET.get('username_query', '')
usernames = (User.objects
.filter(username__startswith=username_query)
.values_list('username', flat=True))
data = {
'usernames': usernames,
}
return JsonResponse(data)
JavaScript
Finally, you need to make a JavaScript function that goes to the database and returns the usernames that match with the value of the input field every time you press (and release) a key. For this, we are going to use Ajax, JQuery and the JQuery-ui's autocomplete function
jQuery(function() {
$("#id_input").on('keyup', function(){
let value = $(this).val();
$.ajax({
url: "{% url 'ajax_autocomplete' %}",
data: {
'username_query': value
},
dataType: 'json',
success: function (data) {
let usernames = data.usernames;
$("#id_input").autocomplete({
source: usernames,
minLength: 3
});
}
});
});
});
And that's it! For more information, you can check out this tutorial
Upvotes: 6
Reputation: 56
I find https://www.w3schools.com/howto/howto_js_autocomplete.asp tutorial to be good. The tutorial uses a static countries array from which the autocomplete function selects the responses(dropdown elements).
Now to make the same more dynamic we can add simple jQuery ajax call to a Django view.
var countries;
$.ajax({
url : '/autocomplete_view';
data : {'query':$('#query').val()};
type : 'GET',
success : function(response){
countries = JSON.parse(response);
// do something extra
},
failure : function(response){
// do something here
},
async : false
});
Upvotes: 1
Reputation: 1036
I know that implementing jQuery autocomplete is tricky. Here is a working example for Django > 2.0:
Step 1: Create a simple HTML with an input (Don't forget to add links to load jQuery and jquery-ui). Save the code as testsearch.html
<head>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.js"></script>
</head>
<div class="ui-widget">
<label for="search"> Search </label>
<input id="search">
</div>
Step 2: Add a JavaScript code to the html. It calls the function autocomplete from jquery-ui. This function uses a source which the URL for Ajax calls
<script type="text/javascript">
$(function() {
$("#search").autocomplete({
source: "{% url 'project:ajax_load_project' %}",
minLength: 2,
});
});
</script>
Step 3: Now we need to create two functions. A simple function to render testsearch.html and another one that receives Ajax calls and send back data.
def ajax_load_project(request):
if request.is_ajax():
q = request.GET.get('term', '')
print(q)
projects = Project.objects.filter(title__istartswith=q)[:5]
results = []
for project in projects:
project_json = {}
project_json['id'] = project.id
project_json['value'] = project.title
project_json['label'] = project.title
results.append(project_json)
data = json.dumps(results)
else:
data = 'fail'
mimetype = 'application/json'
return HttpResponse(data, mimetype)
def searchProject(request):
template = 'project/testsearch.html'
return render(request, template)
Project is my model. You can replace it with your Model. Replace title with the field used for searching.
For my example you can create this simple Model:
class Project(models.Model):
"""
A Model representing a the project.
"""
title = models.CharField(max_length=200)
Step 4: Don't forget to include two URLs. One for the HTML and the one for Ajax calls
urlpatterns += [
#test search
path('SuggestProject/', views.ajax_load_project, name='ajax_load_project'),
path('searchtest/', views.searchProject, name='searchProject'),]
Upvotes: 3
Reputation: 1076
In django 1.10 I use same code
url:
# Ajax
url(r'^search-autocomplete/$', autocompleteModel, name='search-autocomplete'),
view:
def autocompleteModel(request):
search_qs = Account.objects.filter(email__startswith=request.GET['search'])
results = []
for r in search_qs:
results.append(r.email)
resp = request.GET['callback'] + '(' + simplejson.dumps(results) + ');'
return HttpResponse(resp, content_type='application/json')
js:
$(document).ready(function () {
function searchOpen() {
var search = $('#countryId').val();
$.ajax({
url: '/cabinet/search-autocomplete',
dataType: 'jsonp',
type: 'GET',
async: false,
data: injectCsrfToken({
search: search
}),
success: function (data) {
searchResult(data)
},
error: function () {
console.log('error');
}
});
}
function searchResult(data) {
console.log('sdfsdfd');
$( "#countryId" ).autocomplete ({
source: data
});
}
$("#countryId").on('keyup', function () {
searchOpen();
});
});
html:
<input id="countryId" type="text" name="fname">
Upvotes: 0
Reputation: 8535
I found that the simplest way to get started (although probably not the optimal for production) is with JQuery Autocomplete Widget.
The most basic way just requires to copy-paste the code into your html, using an array as a source
:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>jQuery UI Autocomplete - Cities example</title>
<link href="style.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.css">
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
</head>
<body>
<div class="ui-widget">
<label for="tags">Cities: </label>
<input id="tags">
</div>
<script>
$( function() {
var availableTags = [
'Barcelona',
'Berlin',
'London',
'Madrid',
'Rome',
'Paris'
];
$( "#tags" ).autocomplete({
source: availableTags
});
} );
</script>
</body>
</html>
Upvotes: 0
Reputation: 3717
There's a way without using Json:
example: let's assume you have a model named College:
class College(models.Model):
collegeName = models.CharField(max_length=250)
def __str__(self):
return self.collegeName
Now, render a context named 'all_colleges' = College.objects.all() to your template,:
HTML:
<input type="text" id="college"/>
JS:
$( function() {
var availableColleges = [
{% for clg in all_colleges %}
"{{clg}}",
{%endfor%}
];
$( "#clg" ).autocomplete({
source: availableColleges
});
} );
Resources to be included in the template:
<link rel="stylesheet" href="http://code.jquery.com/ui/1.8.18/themes/base/jquery-ui.css" type="text/css" media="all" />
<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.0/jquery-ui.min.js"></script>
That's it!
If you need autocomplete to show options which start with the term entered, modify the default filter autocomplete filter function by adding this snippet in your template:
// over write the default autocomplete function to match the option starting with entered term
$.ui.autocomplete.filter = function (array, term) {
var matcher = new RegExp("^" + $.ui.autocomplete.escapeRegex(term), "i");
return $.grep(array, function (value) {
return matcher.test(value.label || value.value || value);
});
};
Comment if you face any problem :)
Upvotes: 0
Reputation: 385
django-autocomplete-light is very nice option. It is very easy to use and also documented very well. Link: https://github.com/yourlabs/django-autocomplete-light
Documentation: https://django-autocomplete-light.readthedocs.org/en/master/
Upvotes: 1
Reputation: 2166
Meanwhile, a good tutorial appeared.
autocomplete
does everything for you, all you have to do is the following:
js
$(function() {
$("#search-field").autocomplete({
source: "/ajax_calls/myFunction",
minLength: 2,
});
});
urls.py
url(r'^ajax_calls/myFunction/', 'my_app.views.handler_function'),
views.py
def get_drugs(request):
if request.is_ajax():
.....
data = json.dumps(results)
else:
data = 'fail'
mimetype = 'application/json'
return HttpResponse(data, mimetype)
SOURCE: http://flaviusim.com/blog/AJAX-Autocomplete-Search-with-Django-and-jQuery/
Upvotes: 7
Reputation: 5954
If you're looking to search from within your django models then something like:
from django.utils import simplejson
def autocompleteModel(request):
search_qs = ModelName.objects.filter(name__startswith=request.REQUEST['search'])
results = []
for r in search_qs:
results.append(r.name)
resp = request.REQUEST['callback'] + '(' + simplejson.dumps(result) + ');'
return HttpResponse(resp, content_type='application/json')
For the jQuery autocomplete and call:
function searchOpen() {
var search = $('#txtSearch').val()
var data = {
search: search
};
$.ajax({
url: '/search.json',
data: data,
dataType: 'jsonp',
jsonp: 'callback',
jsonpCallback: 'searchResult'
});
}
function searchResult(data) {
$( "#txtSearch" ).autocomplete ({
source: data
});
}
Finally to connect it all on your input form would have something like:
<input type="text" name="search" id="txtSearch" onkeyup="searchOpen()" />
Note, this is using Jquery UI as well in addition to stock jQuery.
Upvotes: 19
Reputation: 4811
I'm a big fan of django-autocomplete: https://bitbucket.org/tyrion/django-autocomplete/wiki/Home . Its got a nice plug-and-play and is very easy to integrate with your own apps without much additional coding.
Upvotes: 4