jQuery Autocomplete + Django + AJAX

Ahora voy a explicar algo técnico pero estético, como utilizar la plugin de jQuery Autocomplete con Django+AJAX, con ella se pueden conseguir efectos como este;

jQuery Autocomplete screenshot
jQuery Autocomplete

Trataré de hacer una consulta por AJAX a una URL cuando tipee 3 o más letras, el código puede ser el siguiente;

$('input').autocomplete({
    minLength:3,
    source: function(req, add){
        $.ajax({
            url: '/ajax/url/',
            async: false,
            dataType:'json',
            type:'POST',
            data: {
                start: function() { return $(this).val(); },
            },
            success: function(data) {
 
                //create array for response objects
                var suggestions = [];
 
                //process response
                $.each(data.items, function(i, val){
                    suggestions.push(val[0]);
                });
 
                //pass array to callback
                add(suggestions);
            }
        });
    }
});

Donde:

  • input: Será el selector del campo de texto al que queremos aplicarle el plugin.
  • minLength: La longitud mínima para hacer la consulta.
  • '/ajax/url/': La URL donde haremos la consulta.
  • start: Va a ser el valor actual del campo de texto, el texto que hemos tipeado y por el que queremos buscar.

La vista podría estar definida como sigue:

def search(request):
 
    if request.method=='GET' or not request.POST.__contains__('start'):
        return HttpResponseForbidden()
 
    # Hacemos la consulta para aquellos elementos que empiecen por start ordenados por nombre
    query = Model.objects.filter(name__istartswith=request.POST['start']).order_by('name')
 
    # Serializamos
    objects = u'{items: [\n'
    for i in query:
        objects += u'{"0":"%s"},\n' % (i.name.replace('"',''))
    objects=objects.strip(",\n");
    objects+=u']}\n'
 
    return HttpResponse(objects,mimetype="text/plain")

También se pueden utilizar serializadores para pasar la información a JSON, pero en este caso he preferido hacerlo a mano.

Para más información visita la página de jQuery.

Un gran número de parejas jóvenes que se enfrentan a varios problemas de saludos cordiales, tales personas pueden comprar medicamentos en línea recta sin orden. Antibióticos de penicilina muy populares que combaten las bacterias. Estos remedios no tratan una infección viral por ejemplo un resfriado común. Vamos a hablar de numerosas drogas existe. Kamagra es un remedio usado para tratar de varias quejas. ¿Qué sabes sobre "Comprar Kamagra Oral Jelly"? Actualmente muchos hombres buscan la frase exacta "comprar kamagra 100mg" en Internet inalámbrico. (Leer más "Kamagra Oral Jelly"). Debido a que algunos de los problemas sexuales son emergencias médicas, es bueno conocer los síntomas. Ciertas personas que usan este medicamento generalmente no tienen efectos secundarios graves Kamagra. El farmacéutico necesita resolver qué dosis es la mejor en su caso. Si el medicamento se usa según sea necesario, es poco probable que esté en un horario de dosificación.

  • Los enlaces estan cerrados
  • Comentarios (20)
    • Serena
    • 10 noviembre 2012 5:52am

    Hola, justamente estoy tratando de colocar una búsqueda con autocompletado de unos de los campos de mi modelo, pero no he logrado hacerlo. Me llama la atención esta técnica que has usado. Sin embargo, no entiendo varias cosas. Será que puedes pasarme un ejemplo simple completo para poder ver todas las cosas necesarias para que funcione. Muchas gracias, mi correo es: serena.luna@gmail.com

    • dugo
    • 10 noviembre 2012 10:37pm

    Hola Serena,

    escríbeme por aquí las dudas que encuentres y estaré encantado de resolverlas 🙂

    1saludo

    • Serena
    • 11 noviembre 2012 6:29pm

    Bueno, por ejemplo en Django según lo que he entendido hasta ahora se debe tener: un modelo, una vista y su correspondiente plantilla. En este ejemplo veo la vista, y asumo que el script que colocaste debe ir en la plantilla. Sin embargo, no veo como asociar la plantilla con la vista (esto debería ser en urls.py), por eso te pedía un ejemplo sencillo completo para ver todo en conjunto funcionando. Gracias por ayudarme.

    • dugo
    • 11 noviembre 2012 9:36pm

    Te explico, en este caso necesitarías dos vistas:

    * Una que te devuelva la plantilla renderizada con el contenido js y HTML.
    * Otra que se encarga de resolver las consultas para el autocompletado, que es la que he escrito arriba.

    Un ejemplo en urls.py;

    ####
    from django.conf.urls.defaults import *

    urlpatterns = patterns(‘myapp.views’,
    url(r’^/url/$’, ‘vista_normal’,), #1
    url(r’^/ajax/url/$’, ‘autocompletado_ajax’,), #2
    )
    ####

    #1 Es la vista que renderiza la plantilla, mediante render_to_response (p.e) y
    #2 Es la vista que he expuesto arriba

    ¿Más claro? 🙂

    • Serena
    • 11 noviembre 2012 10:29pm

    Creo que no he entendido, porque lo he colocado pero no funciona.
    Lo he colocado así:

    # views.py

    #vista 1
    def search_form(request):
    return render_to_response(‘search_prod.html’,context_instance = RequestContext(request))

    #vista 2
    def search(request):

    if request.method==’GET’ or not request.POST.__contains__(‘start’):
    return HttpResponseForbidden()

    # Hacemos la consulta para aquellos elementos que empiecen por start ordenados por nombre
    query = Producto.objects.filter(descripcion__icontains=request.POST[‘start’]).order_by(‘descripcion’)

    # Serializamos
    objects = u'{items: [\n’
    for i in query:
    objects += u'{“0″:”%s”},\n’ % (i.descripcion.replace(‘”‘,”))
    objects=objects.strip(“,\n”);
    objects+=u’]}\n’

    return HttpResponse(objects,mimetype=”text/plain”)

    ###########################################################

    #urls.py

    from django.contrib import admin
    from django.conf import settings

    admin.autodiscover()

    urlpatterns = patterns(”,
    url(r’^search/’,’principal.views.search_form’),
    url(r’^ajax/search’,’principal.views.search’),
    )
    ###########################################################

    #search_prod.html

    {% extends ‘base.html’ %}
    {% block script %}

    {% endblock %}
    $(‘input’).autocomplete({
    minLength:2,
    source: function(req, add){
    $.ajax({
    url: ‘/ajax/search/’,
    async: false,
    dataType:’json’,
    type:’POST’,
    data: {
    start: function() { return $(this).val(); },
    },
    success: function(data) {

    //create array for response objects
    var suggestions = [];

    //process response
    $.each(data.items, function(i, val){
    suggestions.push(val[0]);
    });

    //pass array to callback
    add(suggestions);
    }
    });
    }
    });
    {% block titulo %} Consultar precio de productos {% endblock %}

    {% block encabezado %}
    Consultar precio de productos
    {% endblock %}

    {% block contenido %}

    {% endblock %}

    ###############################################################

    Pero aún no funciona, puedes ver el error?

    • dugo
    • 11 noviembre 2012 11:08pm

    Qué mensaje de error te llega? En el inspector (para Chrome) o firebug (Firefox) puedes ver el resultado de la petición ajax.

    • Serena
    • 11 noviembre 2012 11:48pm

    No me dice el error, simplemente no hace el autocompletado. Pero no viste ningún error en mi código.

    • dugo
    • 11 noviembre 2012 11:55pm

    Ei si! Olvidaste el campo input, tienes que ponerlo

    • Serena
    • 11 noviembre 2012 11:59pm

    Disculpa fue que no se copió completo, lo vuelvo a pegar aqui:

    #search_prod.html
    {% extends ‘base.html’ %}
    {% block script %}

    {% endblock %}
    $(‘input’).autocomplete({
    minLength:2,
    source: function(req, add){
    $.ajax({
    url: ‘/ajax/search/’,
    async: false,
    dataType:’json’,
    type:’POST’,
    data: {
    start: function() { return $(this).val(); },
    },
    success: function(data) {

    //create array for response objects
    var suggestions = [];

    //process response
    $.each(data.items, function(i, val){
    suggestions.push(val[0]);
    });

    //pass array to callback
    add(suggestions);
    }
    });
    }
    });
    {% block titulo %} Consultar precio de productos {% endblock %}

    {% block encabezado %}
    Consultar precio de productos
    {% endblock %}

    {% block contenido %}

    {% endblock %}

    • dugo
    • 12 noviembre 2012 12:05am

    Bienn creo que te falta una cosa, el campo input en el bloque contenido, simplemente pon este código: http://dpaste.com/829405/

    • Serena
    • 12 noviembre 2012 12:34am

    Lo coloque así:

    {% block contenido %}

    {% endblock %}

    no se le debe colocar id=’start’ o name=’start’?

    • Serena
    • 12 noviembre 2012 12:35am

    no me lo muestra en el comentario, por qué?
    Bueno es igual al que me enviaste pero le agrego id=’start’

    • dugo
    • 12 noviembre 2012 12:38am

    En el comentario no te lo muestra porque interpreta el HTML xD

    No es necesario, “start” sólo se utiliza cómo parámetro a enviar, al el id o name del input no se usa.

    • Serena
    • 12 noviembre 2012 12:44am

    Se lo quite y lo vuelvo a probar, pero sigue sin funcionar 🙁 No sé que más hacer…

    • dugo
    • 12 noviembre 2012 12:48am

    Comparte conmigo una carpeta en Dropbox con el proyecto que lo veo en un momento, utiliza mi email rdugomartin@gmail.com

    • Serena
    • 12 noviembre 2012 8:37pm

    Muchas gracias, ahora está funcionando al 100%. Gracias por tu tiempo.

    • dugo
    • 12 noviembre 2012 9:07pm

    De nada Serena, recuerda mostrarme ese proyecto (u otro) cuando esté en producción.

    Un saludo:)

    • Nany
    • 28 marzo 2013 12:06am

    Y qué era el error de Serena? lo que pasa es que también lo estoy implementando en mi código y tampoco me sale el autocomplete.

    • Samuel Cusi Lima
    • 26 julio 2013 6:11pm

    Muchas gracias yo lo hice asi y me fue util tu post:

    en mi vista:
    *******************
    import json

    def getAlgo(request):
    param = request.POST.get(‘param’)
    person = Person.objects.filter(cellular__istartswith=param)

    objects = []
    for i in person:
    objects.append({“cel”: i.cellular_number, “name”: i.full_name})

    return HttpResponse(json.dumps(objects), mimetype=”application/json”)

    ************
    Y en js (jquery)
    /*************/
    $( “#cellular” ).autocomplete({
    source: function( request, response ) {
    $.ajax({
    url: “/get_algo/”,
    dataType: “json”,
    type: “POST”,
    data: {
    param: $(‘#cellular’).val(),
    featureClass: “P”,
    style: “full”,
    maxRows: 12,
    name_startsWith: request.term
    },
    success: function( data ) {
    response( $.map( data, function( item ) {
    return {
    label: item.cel + “, ” + item.name,
    value: item.cel}
    }));
    }
    });
    },
    minLength: 3,
    select: function( event, ui ) {
    //lo que desees
    }
    });

      • dugo
      • 28 julio 2013 5:54pm

      Hola Samuel! Me alegro de lo que encuentres por aquí te sea útil 🙂

      1saludo!

Los comentarios estan cerrados.