entre Desarrolladores

Recibe ayuda de expertos

Registrate y pregunta

Es gratis y fácil

Recibe respuestas

Respuestas, votos y comentarios

Vota y selecciona respuestas

Recibe puntos, vota y da la solución

Pregunta

0voto

¿Crear cuadro de búsqueda con Ajax en Django?

Quetal.

Tengo un template que muestra una lista de estudiantes registrados. Pero cuando ya la lista se hace muy larga se hace tedioso tener que buscar con el scroll hasta por fin encontrar a un estudiante.
Necesito crear entonces, un cuadro de búsqueda que encuentre una cadena de texto cualquiera y si coincide con el nombre o documento de identidad del estudiante, quite la tabla de todos los estudiantes y me ponga una tabla solamente con los datos de el estudiante encontrado. Y si no está, simplemente muestre una etiqueta h3 que diga ¡estudiante no encontrado!

Aquí el truco es que Ajax haga la búsqueda y dependiendo del resultado modifique el template, y todo ello, obviamente, sin recargar la página.

¿cómo puedo lograrlo?

1 Respuesta

2votos

white Puntos75880

Bien, vamos a hacer algunos pasos, hize un codigo con un buscador simple en ajax, no es gran cosa pero es lo básico para que puedas partir desde ese buscador y agregarle mas opciones. me apoye de Jquery y de Jquery UI autocomplete

Paso 1

creando una aplicacion para el ajax.


Ejecuta este comando: python manage.py startapp ajax esto creara una carpeta 'ajax', edita el archivo views.py y agrega este contenido:

from django.shortcuts import render
from django.http import HttpResponseBadRequest, HttpResponse, HttpRequest
from django.contrib.auth.models import User
from django.core import serializers
import re

def search(request):

    # si no es una peticion ajax, devolvemos error 400
    if not request.is_ajax() or request.method != "POST":
        return HttpResponseBadRequest()

    # definimos el termino de busqueda
    q = request.POST['q']

    #verificamos si el termino de busqueda es un documento de identidad
    match = re.match(r'^(?P<CI>[0-9]{2,})$', q)
    isCI = (False, True)[match != None]

    # generamos la query
    if isCI:
        users = User.objects.filter(CI=match.groupdict()['CI'])
    else:
        users = User.objects.filter(username__contains=q)

    # seleccionamos las columnas que deseamos obtener para el json
    user_fields = (
        'username',
        'email',
        'CI'
    )

    # to json!
    data = serializers.serialize('json', users, fields=user_fields)

    # eso es todo por hoy ^^
    return HttpResponse(data, content_type="application/json")

guardalo.

Abre el archivo urls.py y agrega este codigo:

url(r'^ajax/search/', view='ajax.views.search'),

Ahora podras acceder a /ajax/search/ con una petición ajax, he agregado una condicional para que cuando no detecte una peticion ajax devuelva 400

Nota: yo supuse que el identificador de identididad esta en la tabla auth_users, si es asi entonces Agrega este codigo al archivo /ajax/init.py:

from django.db import models
from django.contrib.auth.models import User

ci_field = models.IntegerField()
ci_field.contribute_to_class(User, 'CI')

Paso 2

Agregando el html, js y css.

Donde requieras el buscador, en alguna plantilla, agrega este codigo:

<div id="container">
    <div class="search">
        <div class="searchbox">
            <label>Buscar un estudiante:</label>
            <span class="info">(Puede ser un nombre o el id de identidad)</span>
            <input id="search_input" type="text" name="q">
            {% csrf_token %}
        </div>
        <div class="results">
            <h1 class="error"></h1>
            <div class="wrapper"></div>
        </div>
    </div>
</div>

Agrega los recursos a tu etiqueta <head>:

<link rel="stylesheet" href="{{ STATIC_URL }}styles.css">
<script type="text/javascript" src="https://code.jquery.com/jquery-2.1.3.min.js"></script>
<script type="text/javascript" src="https://code.jquery.com/ui/1.11.2/jquery-ui.min.js"></script>
<script type="text/javascript" src="{{ STATIC_URL }}script.js"></script>

Nota: los recursos los tengo alojados en /django/app/static/

si no tienes esto, en setings.py agrega:

STATIC_URL = '/static/'

STATICFILES_DIRS = (
    os.path.join(BASE_DIR, "static"),
)

y en INSTALLED_APPS agrega:

 'django.contrib.staticfiles',

el código de /static/script.js es:

function __init()
{

    $('#search_input')
        .val('')
        .focus()
        .keyup(function(){

            if(!$.trim($(this).val()))
                $('.results .error').empty().hide();
        });

    var cache = {};
    $('#search_input').autocomplete({
        minLength: 2,
        select: function( event, ui ) {
            return false;
        },
        open: function() {
            $('.results .wrapper').html($(this).autocomplete("widget").html());
            $(this).autocomplete("widget").hide();
        },
        source: function( request, response ) {

            if (cache[request.term]) {
                response(cache[request.term]);
                return;
            }

            $.ajax({
                dataType : 'json',
                method : 'POST',
                url : '/ajax/search/',
                data : {
                    q : encodeURIComponent(request.term),
                    csrfmiddlewaretoken : $('input[name=csrfmiddlewaretoken]').val()
                },
                success : function(data) {
                    var users = [];

                    for(var x in data)
                    {
                        users.push({
                            username : data[x].fields['username'],
                            CI : data[x].fields['CI'],
                            email : data[x].fields['email']
                        });
                    }

                    cache[request.term] = users;
                    response(users);
                }
            });
        },
        response: function(event, ui) {

            if (ui.content.length === 0) {
                $('.results .error').html('No se encontraron resultados').show();
                $('.results .wrapper').empty();
            }
            else
                $('.results .error').empty().hide();
        }
    }).autocomplete('instance')._renderItem = function(ul, item) {

        var user_tmpl = $('<div />')
                        .addClass('user')
                        .append('<a href="/" />').find('a').addClass('username').html(item.username)
                        .parent()
                        .append('<span class="identity"><strong>Identidad:</strong><span></span></span>')
                        .find('.identity > span').append(item.CI)
                        .parent().parent()
                        .append('<span class="email"><strong>Email:</strong><span></span></span>')
                        .find('.email > span').append(item.email)
                        .parent().parent();

        return $('<div></div>')
            .data('item.autocomplete', item)
            .append(user_tmpl)
            .appendTo(ul);
    };
}

$(document).ready(__init);

el código de /static/styles.css es:

body{
    margin: 0;
    padding: 0;
    font-family: monospace;
}

#container{
    width: 1000px;
    margin: 0 auto;
    margin-top: 30px;
}

.ui-helper-hidden-accessible{ display:none!important; }

.search{
    background: #f1f1f1;
    border-bottom: 1px solid #CCCCCC;
    border-radius: 4px;
    padding: 10px;
    width: 750px;
    margin: 0 auto;
}

.search .searchbox{
    border-bottom: 1px solid #DDDDDD;
    padding-bottom: 10px;
}

.search .searchbox label{
    display: block;
    font-weight: bold;
    margin-bottom: 4px;
}

.search .searchbox .info{
    color: #444;
    display: block;
    font-size: 11px;
}

.search .searchbox input{
    border-radius: 0;
    border: 1px solid #DDD;
    border-bottom-width: 2px;
    color: #333;
    font-weight: bold;
    font-size: 14px;
    padding: 7px 10px;
    width: 300px;
}

.search .results{
    border-top: 1px solid #FFFFFF;
    min-height: 20px;
}

.search .results .error{
    display: none;
    background: #e74c3c;
    border-bottom: 2px solid #c0392b;
    color: #FFFFFF;
    padding: 7px 14px;
}

.search .results .wrapper{
    max-height: 400px;
    overflow: auto;
}

.search .results .wrapper div.user
{
    margin: 10px;
}

.search .wrapper div.user .username,
.search .wrapper div.user .email,
.search .wrapper div.user .identity{
    display: block;
}

.search .wrapper div.user .email,
.search .wrapper div.user .identity{
    color: #555;
    font-size: 11px;
}

.search .wrapper div.user .username{
    color: #2980b9;
}

.search .wrapper div.user .username{
    font-weight: bold;
    font-size: 15px;
}

quedando algo asi:

none
none

Un ejemplo de este buscador simple lo puedes ver online en http://jsfiddle.net/m880wdnu/embedded/result/ obviamente este demo no utiliza ajax por obvias razones.

0voto

carlossevi comentado

¡Demasiado buena la respuesta!

0voto

maxgonpe comentado

@white De verdad te felicito por tu dedicación. Estoy buscando un equivalente a lo que hace html5 y que tambien se puede hacer en PHP de que ha medida de que se va typeando en el cuadro de texto del filtro las filas se van borrando y solo quedan las o la que cumple el criterio o ninguna; He leído tu respuesta, pero me pierdo en algunos intermedios.
1) la view.py donde hay que pegar el codigo del primer cuadro , es en la app ajax?

2) incluyo app ajax en el setting??

3) esta url(r'^ajax/search/', view='ajax.views.search'), -  va en app ajax o en el proyecto principal?

4) no estoy trabajando con los modelos de user, sino un modelo cualquiera con 3 o cuatro campos   campo1, campo2 ... campox  .  debo incluir esa informacion  en el archivo /ajax/init.py ??

5) puedes re-enviar tu codigo con mas detalles por favor

6) tu respuesta es del 2015, solo espero te acuerdes y aun estes en estos quehaceres?

7) sino cualquiera que tenga el asunto claro y lo pueda compartir, estaría muy agradecido.

0voto

Peter comentado

@maxgonpe por favor abre otra pregunta con tu duda.

Saludos.

0voto

maxgonpe comentado

Si, lo hice. Grácias

Por favor, accede o regístrate para responder a esta pregunta.

Otras Preguntas y Respuestas


...

Bienvenido a entre Desarrolladores, donde puedes realizar preguntas y recibir respuestas de otros miembros de la comunidad.

Conecta