LogoEjk

TEST

Motor de b煤squeda de citas de los Simpsons con Django

March 13, 2016

En esta entrada, modificaremos nuestra aplicaci贸n para que sea interactiva. Concretamente, crearemos un buscador simple que nos devolver谩 las citas que contengan ciertas palabras.

En la entrada anterior, creamos una aplicaci贸n b谩sica en Django que devolv铆a citas aleatorias de los Simpson. La aplicaci贸n no era interactiva, es decir, no procesaba la petici贸n del cliente. En esta entrada, modificaremos nuestra aplicaci贸n para que sea interactiva. Concretamente, crearemos un buscador simple que nos devolver谩 las citas que contengan ciertas palabras.

Para empezar, plantearemos la interfaz de nuestra aplicaci贸n en torno al protocolo de comunicaci贸n cliente-servidor. Para ello, vamos a revisar dos tipos de peticiones HTTP: las de tipo GET, que suelen usarse para solicitar documentos, y las de tipo POST, que suelen usarse para enviar informaci贸n del cliente al servidor. En la entrada anterior, nuestra aplicaci贸n s贸lo reaccionaba a la recepci贸n de peticiones GET. Ahora, a帽adiremos la capacidad de procesar las peticiones POST. Estas peticiones contendr谩n las palabras de b煤squeda enviadas por el cliente. Las peticiones GET se pueden usar para esto tambi茅n, mediante el uso de par谩metros en el URL; pero dejaremos eso de lado por el momento.

Desde el punto de vista del cliente, la petici贸n POST se genera en un elemento form de un documento HTML. Este documento deber谩 ser enviado por el servidor, respondiendo a una primera petici贸n del cliente. El intercambio de peticiones y respuestas HTML es un poco m谩s complicado en esta aplicaci贸n.

requestsES

En primer lugar, veamos c贸mo es el primer documento HTML, y dejaremos para m谩s adelante c贸mo implementar el protocolo. El c贸digo m铆nimo es el siguiente:

<html>
<head>
<title>Buscar citas de los Simpsons</title>
</head>
<body>
<form action='buscarCita' method='POST'>
<input type='text' name='palabras' /> <input type='submit' value='Buscar' />
</form>
</body>
</html>

La vista que estamos dise帽ando, deber谩 devolver este documento cuando reciba una petici贸n GET, y procesar y devolver los resultados de la b煤squeda cuando reciba una petici贸n POST. Estos resultados tambi茅n se devolver谩n como un documento HTML. El proceso de b煤squeda consistir谩 en un filtrado del contenido de las citas, de modo que contengan todos los t茅rminos de b煤squeda. El c贸digo resultante ser谩 el siguiente:

def buscarCita(request):
if request.method == 'GET':
# Primera petici贸n del cliente
return HttpResponse(htmlcode)
else:
# Segunda petici贸n (b煤squeda)
palabras = request.POST['palabras'].split()
if len(palabras) >= 1:
resultados = SimpsonQuote.objects.filter(content__icontains = palabras[0])
for palabra_adicional in palabras[1:]: # Filter by any additional terms
resultados = resultados.filter(content__icontains = palabra_adicional)
if len(resultados) > 0:
respuesta = '<html><head><title>Search results</title></head><body>'
for cita in resultados:
respuesta += '<p>"' + cita.contenido + '" ' + cita.personaje + ' (T' + str(cita.temporada) + 'C' + str(cita.capitulo) + ')</p>'
respuesta += '</body></html>'
return HttpResponse(respuesta)
else:
return HttpResponse('No hay resultados')
else:
# Controlar el caso de que el cliente env铆e una petici贸n vac铆a
return HttpResponse('Por favor, introduce t茅rminos de b煤squeda')

La vista primero determina el tipo de petici贸n. Si es una petici贸n POST, extraer谩 de ella los t茅rminos de b煤squeda. Si hay al menos uno, filtrar谩 las entradas de la base de datos en busca de ese t茅rmino y luego, entre los resultados, en busca del resto de los t茅rminos. Si se obtienen resultados, los devuelve al cliente. En cualquier otro caso, se devuelve un mensaje de error al usuario.

Este c贸digo es, por desgracia, incompatible con ciertas caracter铆sticas de seguridad de Django, por lo que tendremos que cambiar nuestra configuraci贸n para poder ejecutarlo. Concretamente, necesitamos deshabilitar la protecci贸n CSRF. En la pr贸xima entrada, cuando refinemos nuestro uso de las respuestas, podremos volver a la configuraci贸n segura. Hecha esta advertencia, procedamos. Editamos el fichero SQproject/settings.py y comentamos la l铆nea que activa el middleware de protecci贸n CSRF:

MIDDLEWARE_CLASSES = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
#'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

Nunca debemos hacer esto en un entorno de producci贸n. Lo hacemos aqu铆 para mantener el c贸digo de la vista simple (Haz lo que digo, no lo que hago).

Finalmente, a帽adimos una entrada en SQproject/urls.py:

from django.conf.urls import url
from django.contrib import admin
from HWapp.views import randomquote, buscarCita

urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^cita/', citaAleatoria),
url(r'^buscar/', buscarCita),
]

Hemos a帽adido tambi茅n buscarCita a las importaciones.

Y ya est谩. Activamos el servidor de desarrollo ejecutando python manage.py runserver y accediendo a http://127.0.0.1:8000/buscar/. Ya podemos buscar en nuestra colecci贸n de citas que contengan cierta palabra. Con este sencillo ejemplo, hemos cubierto la funcionalidad total de una aplicaci贸n interactiva que sirve datos respondiendo a peticiones concretas; no muy distinta a una base de datos. Al hacer esto, hemos cometido dos pecados: hemos deshabilitado parte de la seguridad de Django, y hemos incluido c贸digo HTML en nuestra vista (violando el principio modelo-vista-controlador). Ambos problemas se resolver谩n en la siguiente entrada, cuando veamos c贸mo usar plantillas de respuesta.

Return to blog