Mostrando entradas con la etiqueta templates. Mostrar todas las entradas
Mostrando entradas con la etiqueta templates. Mostrar todas las entradas

martes, 28 de febrero de 2023

12.- Desarrollo Práctico de una aplicación. Creación Proyecto, Aplicación, Primeras vistas y Plantillas.

Vamos a crear una aplicación completa de Django y a la vez profundizando más en varios conceptos. La aplicación que crearemos tendrá cinco vistas:

  • Inicio
  • Servicios
  • Tienda 
  • Blog
  • Contacto
Todo lo que sigue ya lo hemos visto en capitulos previos, asi que no me detendré a comentarlo. Comenzaremos creando el proyecto con el nombre que queramos, en mi caso usaré PracticaDjango:


$ django-admin startproject PracticaDjango

Esto nos creará un directorio con la siguiente estructura:

PracticaDjango       > Directorio Padre 
    manage.py        > Archivo de gestión de Django.
    PracticaDjango --> Es un directorio

Es siguiente caso es crear la aplicación que gestionará la aplicación web. Así que entramos en el directorio padre y creamos la aplicación:

PracticaDjango$ python manage.py startapp Proyecto_web_app

Salida:

PracticaDjango       > Directorio Padre 
    manage.py        > Archivo de gestión de Django.
    PracticaDjango --> Es un directorio
    Proyecto_web_app > El directorio de la app recien creada.

Recuerda que una cosa es el proyecto y otra la aplicación. En Django dentro de un proyecto puedes tener muchas aplicaciones.

Ahora es un buen momento para verificar que nuestro proyecto funciona, así que vamos a la consola y ejecutamos el servidor:

PracticaDjango$ python manage.py runserver

Abrimos el navegador y entramos en localhost:8000 y si todo ha ido bien verás la siguiente pantalla:

pantalla inicio de Django

Seguidamente creamos de forma sencilla las vistas de cada una de las cinco url de la aplicación. Para ello vamos al archivo views.py y para hacer algunas pruebas importamos la clase HttpResponse.

PracticaDjango/Proyecto_web_app/views.py

from django.shortcuts import render, HttpResponse

# Create your views here.

def home(request):
    return HttpResponse('Home')

def servicios(request):
    return HttpResponse('Servicios')

def tienda(request):
    return HttpResponse('Tienda')

def blog(request):
    return HttpResponse('Blog')

def contacto(request):
    return HttpResponse('Contacto')

Ahora nos vamos a registrar las URLS. Importamos las vistas y luego registramos las direcciones.

PracticaDjango/PracticaDjango/urls.py

from django.contrib import admin
from django.urls import path
from Proyecto_web_app import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', views.home, name='home'),
    path('servicios/', views.servicios, name='servicios'),
    path('tienda/', views.tienda, name='tienda'),
    path('blog/', views.blog, name='blog'),
    path('contacto/', views.contacto, name='contacto'),
]

Volvemos a ejecutar el servidor, si lo hemos cerrado y probamos cada una de las url, para ver que todas las vistas funcionan.

Ej para la vista blog.

vista blog funcionando correctamente


Reorganización de las url para un mejor funcionamiento.


Hay que tener en cuenta que nosotros creamos un proyecto en Django y este puede tener varias aplicaciones. De igual forma es muy frecuente que una aplicación Django la puedas reaprovechar en diferentes proyectos. Hasta ahora registramos nuestras Urls dentro del archivo urls.py que estaba en PracticaDjango. Pero imaginaros si tuviéramos que registrar en el las urls, no de una única aplicación, sino de tres, cuatro o quince aplicaciones. En este caso este archivo tendría muchísimo código y nos seria complicado saber que urls son de una aplicación y cual de otra. Así que lo bueno es que las urls de cada aplicación estén dentro de su directorio. 

Para ello seguimos las instrucciones que ya nos indica Django en el archivo urls.py del Proyecto.

1.- Creamos un archivo llamado urls.py pero dentro de la aplicación.

2.- Luego dentro de ese archivo importamos el path

PracticaDjango/Proyecto_web_app/urls.py

from django.urls import path

3.- A continuación importamos las vistas de la aplicación.

PracticaDjango/Proyecto_web_app/urls.py

from django.urls import path
from . import views

4.- Tenemos que trabajar con la lista urlpatterns y para no tener que escribir tanto, vamos al url del proyecto, copiamos el urlpatterns y lo pegamos aquí. Lógicamente quitamos la vista admin que no corresponde a la aplicación, sino al proyecto.

PracticaDjango/Proyecto_web_app/urls.py

from django.urls import path
from Proyecto_web_app import views

app_name = "Proyecto_web_app"

urlpatterns = [
    path('', views.home, name='home'),
    path('servicios/', views.servicios, name='servicios'),
    path('tienda/', views.tienda, name='tienda'),
    path('blog/', views.blog, name='blog'),
    path('contacto/', views.contacto, name='contacto'),
]


'app_name' en Django se utiliza para definir un nombre único para la aplicación, evitando conflictos de nombres con otras aplicaciones que pudiéramos crear luego.

'name' se asigna a cada URL dentro de la aplicación y proporciona una etiqueta única para esta URL en nuestro proyecto.

Estos atributos nos ayudarán a a organizar y referenciar fácilmente las URLs en nuestro código y en las plantillas de Django.  Por ejemplo cuando más adelante tengamos que construir una URL en una plantilla en vez de usar una referencia absoluta para referirnos a la vista 'home' haremos referencia a ella como 'Proyecto_web_app:home'.

Y como hemos movido todas las vistas de la aplicación, en el archivo urls.py del PROYECTO quitamos todo lo que hemos movido y dejamos solo el admin. Quitamos también la importación de las vistas. En definitiva lo dejamos como estaba al principio. Solo nos falta enlazar el url del proyecto con el url de la aplicación, lo haremos a través del path como nos pone Django en la documentación de este mismo archivo, usando el comando 'include' que previamente habremos de importar.

PracticaDjango/PracticaDjango/ulrs.py

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls), 
    path('proyecto_web_app/', include('Proyecto_web_app.urls')), 
]

Llegado este punto, tenemos que comprobar que funcionan bien las urls teniendo en cuenta el path que acabamos de escribir. Para acceder a las vistas tendríamos que hacer lo siguiente. Vamos a ver como acceder a una con un ejemplo.

aceso a url tienda
Pero al hacer esto, hemos complicado un poco la url porque tenemos que agregar 'proyecto_web_app', que es el nombre de nuestro proyecto. Si queremos teclear las urls como antes, que sin poner nada nos llevaba a las vistas, tenemos que ir al urls del proyecto y en el path tenemos que dejar vacía la raíz para que no haya que poner nada y así, funcionaría como al principio.

PracticaDjango/PracticaDjango/urls.py 

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('Proyecto_web_app.urls')),  
]

url acortada de la aplicación

Plantillas de las vistas.


Nos vamos a la carpeta de la aplicación y creamos una carpeta llamada 'templates' y dentro de esta carpeta crearemos otra con el nombre también de la aplicación que será donde depositaremos las plantillas html. Tenemos que crear una plantilla para cada una de las vistas. Vamos a hacer una como ejemplo para la vista inicio pero tenemos que crear otras iguales para el resto.

PracticaDjango/Proyecto_web_app/templates/Proyecto_web_app/home.html

<!DOCTYPE html>
<html lang="en">
<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>Home</title>
</head>
<body>
    Home
</body>
</html>
Ahora debemos modificar el archivos de las vistas de la aplicación para que renderice las plantillas que habremos creado. Pero para que esto funcione es IMPORTANTE registrar nuestra aplicación. Tenemos que ir al archivo settings.py del proyecto y el la lista de INSTALLED_APPS tenemos que registrar la aplicación.

PracticaDjango/PracticaDjango/settings.py

...
# Application definition

INSTALLED_APPS = [
    # Nuestras aplicaciones.
    'Proyecto_web_app.apps.ProyectoWebAppConfig',
    # Aplicaciones por defecto.
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]
...

Podemos aprovechar este mismo archivo para modificar nuestra hora local (TIME_ZONE) y el idioma (LANGUAGE_CODE) como ya vimos en el capitulo 1.

Después de lo anterior, ya solo nos queda modificar el archivo de las vistas de la aplicación para que se rendericen cada una de las vistas cuando se llame a la url correspondiente.

PracticaDjango/Proyecto_web_app/views.py

from django.shortcuts import render, HttpResponse

# Create your views here.

def home(request):
    return render(request, 'Proyecto_web_app/home.html')

def servicios(request):
    return render(request, 'Proyecto_web_app/servicios.html')

def tienda(request):
    return render(request, 'Proyecto_web_app/tienda.html')

def blog(request):
    return render(request, 'Proyecto_web_app/blog.html')

def contacto(request):
    return render(request, 'Proyecto_web_app/contacto.html')

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>