malisit
malisit

Reputation: 1258

Django autocomplete from db

I have a model like this:

class Baslik(models.Model):
    user = models.ForeignKey(User, null=True, blank=True)
    title = models.CharField(max_length=50)
    timestamp = models.DateTimeField(auto_now_add=True, auto_now=False)
    updated = models.DateTimeField(auto_now_add=False, auto_now=True)
    active = models.BooleanField(default=True)

I want to autocomplete an input in template according to this model's title field. I just want autocomplete for title anything else would not work for me? I think it should be done with jquery, ajax etc. I don't have any idea about them. Is there any way to do this? Is there any packages for exact same thing? Thanks.

Upvotes: 2

Views: 1690

Answers (2)

Alvaro
Alvaro

Reputation: 12037

I use bootstrap's typeahead plugin, with its Bloodhound engine that let's you use remote sources. Docs and examples here.

You simple have to write a JSON response view that processes the request made by the typeahead

Edits needed for the js code: You could use something like the following:

var source = new Bloodhound({
    hint: false,
    datumTokenizer: Bloodhound.tokenizers.obj.whitespace('description'),
    queryTokenizer: Bloodhound.tokenizers.whitespace,
    remote: YOUR_JSON_VIEW_URL + '&query=%QUERY'
    });

    source.initialize();

This will initialize a source pointing to your JSON view. Please note that Bloodhound will fill the %QUERY parameter with wathever the user types.

After that, we need to tell the typeahead to use this source:

$(typeahead_input).typeahead(null, {
        name: 'some_name',
        displayKey: 'description',
        source: source.ttAdapter() }

Note the displayKey I have specified, that's the attribute displayed by the typeahead, now, onto the view:

We will have something like:

from django.views.generic import View

class MyJsonView(View):

    def get(self, request):
        context = []
        querystring = request.GET.get('query', None)
        if querystring:
            instances = MyModel.objets.filter(somefield__icontains=querystring)
            for ins in instances:
                 context.append({'id': ins.id, 'description' ins.display_field})
        json_context = json.dumps(context)
        return HttpResponse(json_context, {'content_type': 'application/json'})

Upvotes: -1

klasske
klasske

Reputation: 2174

ui-autocomplete-input works pretty well for this.

Generate the list in your template

<script>
$(function() {
var availableTitles = [
   {% for baslik in basliks %}
      "{{ baslik.title}}" {% if not forloop.last %},{% endfor %}   
   {% endfor %}

];
$( "#tags" ).autocomplete({
  source: availableTitles
});
});
</script>

<div class="ui-widget">
  <label for="tags">Tags: </label>
  <input id="tags">
</div>

EDIT (based on comments): Added a json response; this would be needed in both the ui-autocomplete and bootstrap/typeahead.js solution

import json

from django.http import HttpResponse

def json_response_view(request):
   q = request.GET.get('q', '')
   response_data = Baslik.objects.filter(title__startswith=q).values("title")
   return HttpResponse(json.dumps(response_data), content_type="application/json")

Upvotes: 2

Related Questions