2

I'm trying to write a simple search server, using Django with AJAX. The server itself works fine, but I am still struggling with adding autocomplete to the search widget.

(I don't want to use available Django snippets, since they don't do exactly what I want, are hard to customize, and don't teach me the basics the way writing the interface from scratch does)

On the client (Javascript) side, I'm using YUI because it looks simpler - but don't mind switching to jQuery, so please don't fixate on that.

In YUI, an autocomplete box takes three parameters: input,container and dataSource. The first two are just the widgets, and the third one is interesting.

If I write:

var oDS = new YAHOO.util.LocalDataSource(["apples","apples2", "broccoli", "cherries"]);
var oAC = new YAHOO.widget.AutoComplete("myInput", "myContainer", oDS);

in my <script>, I get an autocomplete box which autocompletes these terms.

When I try to replaces the LocalDataSource with a remote datasource, for example by choosing var oDS = new YAHOO.util.ScriptNodeDataSource("127.0.0.1:8000/getNames/"), and setting up an apropriate view, no autocomplete happens.

What I know about the problem:

  1. I know that the view gets called (by debug printing) - so that isn't the problem.
  2. I return a json array by jresponse = simplejson.dumps(response_array); return HttpResponse(jresponse, mimetype='application/javascript'); I don't think there's any problem with that, since I can access that view directly and get a textual representation of the json when I do.
  3. Maybe there's a problem with the input-type that the local data source expects - I'm not sure how to set it.

Any help (including how to do this correctly in jQuery - I don't mind dumping YUI) would be much appreciated.


Edit: After the first two comments (thanks!), I installed firebug, and started playing with it. It's really messy, however, since the Yahoo toolbar has lots of code, and I don't know where to break it. Is there some easy way to have firebug only show me json/xml elements?

@Marat: I did that already (accessing my view), and it returns a string representation of the JSON (at least that's what my browser shows). Is that what I should expect?

@pastylegs: Here's the code:

 <div id="myAutoComplete">
    <input id="myInput" type="text">
    <div id="myContainer"></div>
    </br></br>
    <input type="submit">
</div>

 <script type="text/javascript">
YAHOO.example.BasicLocal = function() {
{%block oDS%}
// Use a LocalDataSource
var oDS = new YAHOO.util.LocalDataSource(["apples","apples2", "broccoli", cherries"]);
//for remote - oDS = new YAHOO.util.ScriptNodeDataSource("127.0.0.1:8000/getNames/")


// Instantiate the AutoComplete
var oAC = new YAHOO.widget.AutoComplete("myInput", "myContainer", oDS);
oAC.prehighlightClassName = "yui-ac-prehighlight";
oAC.useShadow = true;

return {
    oDS: oDS,
    oAC: oAC
};
}();
</script>

The Django view:

def getNamesXML(request):
    response_array=['Apples','Oranges']
    print response_array
    jresponse = simplejson.dumps(response_array)
    print jresponse
    return HttpResponse(jresponse, mimetype='application/javascript')

Thanks a lot!

Guy Adini
  • 4,538
  • 2
  • 29
  • 31
  • Can you post the relevant javascript and django view? – Timmy O'Mahony Nov 06 '11 at 09:50
  • First, check you can open view manually (ie open 127.0.0.1:8000/getNames/) If it doesn't work - error is in your view. If it does, check communication between your browser and server (use Firebug, developer console, or whatever). If no communication happens, you have error in JS, else something is wrong with way you pass datasource. – Marat Nov 06 '11 at 10:19
  • Autocomplete is my bane too. I *think* that you also need to set up the autocomplete parser in your oDS configuration. Not sure how though, something with oDS.doBeforeCallback = function (request, raw, response, query) { //do your parsting here }; – Zlatko Nov 16 '11 at 15:51

1 Answers1

1

I don't know anything about YUI, but I can give you a working jQuery example. Main difference I see with your code is the mimetype: as discussed in this question, you should use application/json. That said, I don't think it'll make a big difference.

For the view, use something along these lines:

def autosuggest(request):
    query = request.GET.get('term') # jQuery autosuggest input so far
    f = MyModel.objects.filter(name__icontains=query)
    response = [p[0] for p in f.order_by("name")[:10].values_list("name")]
    return HttpResponse(simplejson.dumps(response), mimetype="application/json")

This assumes f is a QuerySet on a model that has a name field, and you want the first 10 matches. In your template, the following should do:

$('#myInput').autocomplete({
    source: '{% url myapp.views.autosuggest %}',
    minLength: 2, // Two characters are needed before suggestions show
    select: function(event, ui) { // Callback function for selection
        $('#myInput').val(ui.item.value);
    },
});
Community
  • 1
  • 1
jro
  • 8,540
  • 27
  • 33
  • Thanks a lot! I'm a real newbie at all this client side business, and this still doesn't work properly for me, but I totally understand what's supposed to happen, and will make it happen once I figure out what I'm doing wrong with the jQuery. – Guy Adini Nov 07 '11 at 17:38
  • Also - sorry for not upvoting, I don't have enough rep yet. But you did help me a lot. – Guy Adini Nov 07 '11 at 17:38
  • The example was missing a pound sign (#) for the identifier, perhaps that was something. Updated now. – jro Nov 07 '11 at 18:07