miércoles, 1 de febrero de 2023

9.- Django - Formularios.

Vamos a ver como crear un formulario, de momento de forma manual y luego como enviar la información al servidor.

- Request object Django.

Empezamos creando la carpeta que contendrá las plantillas de formularios, como ya dijimos en capítulos anteriores se puede usar cualquier nombre pero por convención se utiliza "templates". (al crearla con este nombre dentro del proyecto no hace falta registrarla.)



Ahora dentro de esta carpeta creamos el archivo html que contendrá el formulario: busqueda_juegos.html.

Creamos una estructura típica de html, para diseñar el formulario. Es muy sencilla, solamente un cuadro donde meter texto y un botón para enviar el formulario.

gestionPedidos/templates/busqueda_juegos.html

<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Busqueda de Productos</title>
</head>
<body>
    <form action="/buscar/" method="get">
        <!-- Cuadro de texto de entrada -->
        <input type="text" name="prd">
        <input type="submit" value="Buscar">
    </form>
</body>
</html>

Cuando pulsemos el botón enviar de este formulario nos debe llevar a una dirección llamada /buscar/ que crearemos luego. Como medio de trasporte usaremos el método GET para enviar la información, aunque luego veremos como usar el método POST y sus diferencias.

Identificamos la información que enviaremos en el cuadro de texto con el nombre de "prd" ya que tendremos que rescatarla luego.

Ahora que tenemos el formulario creado, tenemos que crear una vista que nos lleve al mismo. Así que nos vamos al archivo views.py y allí definimos la vista que nos va a devolver el renderizado del formulario.

from django.shortcuts import render

# Create your views here.

def busqueda_juegos(request):
    return render(request, "busqueda_juegos.html")
Tenemos que registrar la URL que nos lleve a este formulario en el archivo tiendaVirtual/urls.py

from django.contrib import admin
from django.urls import path
# Siempre hay que importar las vistas de la aplicación
from gestionPedidos import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('busqueda_juegos/', views.busqueda_juegos),
]
Vamos a probarlo. Ejecutamos el servidor de Django:

$ python manage.py runserver

y accedemos a la dirección que hemos registrado para el formulario:

formulario de busqueda de juegos
Aunque aun no hace nada, porque no hemos construido la página o url a donde se enviará el formulario /buscar/

Vamos con ello. Creemos una vista y registrémosla luego en el PATH. Cuando esta vista reciba la información del formulario a través del método request.GET[] lo almacenará en la variable mensaje y lo mostrará en pantalla. 'prd' se corresponde a lo que estaba almacenado en el cuadro de texto.

gestionPedidos/views.py

from django.shortcuts import render
from django.http import HttpResponse

# Create your views here.

def busqueda_juegos(request):
    return render(request, "busqueda_juegos.html")

def buscar(request):
    mensaje = f"Articulo Buscado: {request.GET['prd']}"
    # como request.GET es un diccionario se podría usar también
    # mensaje = f"Articulo Buscado: {request.GET.get('prd')}
    return HttpResponse(mensaje)
Nos falta registrar esta vista en el url.

tiendaVirtual/urls.py

from django.contrib import admin
from django.urls import path
# Siempre hay que importar las vistas de la aplicación
from gestionPedidos import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('busqueda_juegos/', views.busqueda_juegos),
    path('buscar/', views.buscar),
]

y ahora si vamos al navegador y entramos en la url /busqueda_juegos/ y tecleamos cualquier cosa y lo enviamos, nos mostrará eso mismo que hayamos puesto en la pantalla.

Lo que vamos a hacer ahora es que la información introducida en el formulario sirva para hacer búsquedas en la base de datos que teníamos creada. La idea es que vayamos al formulario e introduzcamos el nombre de un juego. 

El ordenador busque ese nombre en la base de datos de los artículos (gestionpedidos_Articulos) dentro del campo "nombre" y en el caso en el que este, nos devuelva la información de todos los campos de ese articulo (nombre, categoría y precio). Si no está nos dirá que el artículo no se ha encontrado.

Hasta ahora esto son los juegos que están en la base de datos.

juegos registrados en la base de datos

Antes de ponernos con ello tenemos que solucionar un pequeño problema. Este es, que si en el formulario no tecleas nada y pulsas el botón de enviar no te sale nada. Hasta ahora esto no era un problema pero si puede serlo si buscas "nada" en una base de datos.

Para ello nos vamos al archivo de vitas e introducimos un condicional para que si el formulario viene vacío, nos lo indique.

gestionPedidos/views.py

...
# Create your views here.

def busqueda_juegos(request):
    return render(request, "busqueda_juegos.html")

def buscar(request):
    # Condicional para verificar que el formulario no 
    # venga vacio.
    if request.GET['prd']:
        mensaje = f"Articulo Buscado: {request.GET['prd']}"
    else:
        mensaje="No se ha introducido información para buscar el producto."
    
    return HttpResponse(mensaje)

Una vez hecho lo anterior vamos a buscar un juego en la base de datos. 

Voy a escribir el código y luego lo comento. Empezamos yendo al archivo de vistas views.py


gestionPedidos/views.py

from django.shortcuts import render
from django.http import HttpResponse
# Para poder usar el modelo Articulos de la base de datos
from gestionPedidos.models import Articulos

# Create your views here.

def busqueda_juegos(request):
    return render(request, "busqueda_juegos.html")

def buscar(request):
    # Condicional para verificar que el formulario no 
    # venga vacio.
    if request.GET['prd']:
        # mensaje = f"Articulo Buscado: {request.GET['prd']}"
        juego=request.GET['prd']
        items = Articulos.objects.filter(nombre__icontains=juego)
        return render(request, "resultados_busqueda.html", {'items':items, 'query':juego})
    else:
        mensaje="No se ha introducido información para buscar el producto."
    
    return HttpResponse(mensaje)
Comenzamos importando el modelo Articulos para poder trabajar con el.

La instrucción del mensaje la voy a comentar por no borrarla. Luego creo la variable "juego" que almacenará lo que viene desde el formulario. Después creamos otra variable "items" que recogerá los juegos que existan en la base de datos que cumplan el criterio de búsqueda. Esto lo conseguimos usando el método filter junto el nombre del campo seguido con la propiedad con doble guion bajo __icontains.

Esto equivale en lenguaje SQL a:


* item es lo que viaje dentro de la variable juego.

En el campo "nombre" de la base de datos busca cualquier cosa que contenga la palabra que vaya en item. Es como si tuviese caracteres comodín por delante y por detrás de la palabra que vaya en item. 

Ejemplo.  Si en el formulario tecleo la palabra "of" buscará en la base de datos, por el campo nombre todos los registros que tengan delante, en medio, contengan o tengan detrás la palabra of. No distingue en la búsqueda entre mayúscula o minúsculas, da igual.

__icontains

Ahora vamos a construir el html que muestra la información, que es el que se ve arriba. Terminamos primero con el archivo de vistas y le decimos al archivo de vistas que nos renderice el request llamandodo al archivo "resultados_busqueda.html" (que aun no tenemos creado) y que nos renderice los resultados de la búsqueda.

 return render(request, "resultados_busqueda.html", {'items':items, 'query':juego})

El archivo "resultados_busqueda.html" es el siguiente:


gestionPedidos/templates/resultados_busqueda.html.py

<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Resultados Busqueda</title>
    <style>
        td {
          text-align: center;
        }
    </style>
</head>
<body>
    <p>Estas buscando: <strong>{{query}}</strong></p>
    <table border="1">
    {% if items %}
        <h4>Artículos encontrados: {{items|length}} juegos</h4>
        <!-- Recorremos la lista -->
        <tr>
            <th>Nombre</th>
            <th>Categoria</th>
            <th>Precio</th>
        </tr>
        {% for item in items%}
            <tr>
                <td>
                    {{item.nombre}} 
                </td>
                <td>
                    {{item.categoria}}
                </td>
                <td>
                    {{item.precio}}
                </td>
            </tr>    
        {% endfor %}
        
    {% else %}
        <p>La información solicitada no existe.</p>
    {% endif %}
    </table>
</body>
</html>

    

Recorremos los datos encontrados a través de un bucle y mostrando los resultados en una tabla de html.

¿Cómo limitar el número de caracteres a buscar en la base de datos?


Si dejamos que el usuario introduzca un número ilimitado de caracteres en el campo de búsqueda esto podría ralentizar las búsquedas y el servidor, causando problemas. Esto es muy sencillo y lo realizaremos con un condicional de Python en el archivo de las vistas.

gestionPedidos/views.py

....
def buscar(request):
    # Condicional para verificar que el formulario no 
    # venga vacio.
    if request.GET['prd']:
        # mensaje = f"Articulo Buscado: {request.GET['prd']}"
        juego=request.GET['prd']
        if len(juego)>20:
            mensaje = "El texto de busqueda es demasiado largo (max 20 caracteres)"
        else:
            items = Articulos.objects.filter(nombre__icontains=juego)
            return render(request, "resultados_busqueda.html", {'items':items, 'query':juego})
    else:
        mensaje="No se ha introducido información para buscar el producto."
    
    return HttpResponse(mensaje)
Otra forma es definirlo en dentro de la plantilla "busqueda_juegos.html" dentro del formulario en la etiqueta <input> con el atributo maxlength, de la siguiente forma:

gestionPedidos/templates/busqueda_juegos.html

<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Busqueda de Productos</title>
</head>
<body>
    <form action="/buscar/" method="get">
        <!-- Cuadro de texto de entrada -->
        <input type="text" name="prd" maxlenght=20>
        <input type="submit" value="Buscar">
    </form>
</body>
</html>



No hay comentarios:

Publicar un comentario