Diferencias entre las revisiones 59 y 60
Versión 59 con fecha 2021-06-03 20:44:46
Tamaño: 28401
Comentario:
Versión 60 con fecha 2021-06-03 20:46:27
Tamaño: 28590
Comentario:
Los textos eliminados se marcan así. Los textos añadidos se marcan así.
Línea 399: Línea 399:
{{{#!highlight python
class Mascota(models.Model):
    nombre = models.CharField(max_length=200)
    edad = models.IntegerField()

    def __str__(self):
        return self.nombre
}}}
Línea 400: Línea 408:

Primeros pasos con Django

Introducción:

Django es un framework de desarrollo web de código abierto, escrito en Python, que respeta el patrón de diseño conocido como MVC (Modelo–Vista–Controlador)

Homepage: https://www.djangoproject.com/
Documentación: https://docs.djangoproject.com/es/3.1/

Instalación:

Preparando el entorno de trabajo

Instalar módulo para crear entornos virtuales en Python (3):

# apt install python3-venv

Creamos una carpeta para crear nuestros proyectos Django.

$ mkdir django
$ cd django

Creamos un entorno virtual para Python 3.8 (dependerá la versión que tengan instalada):

$ python3 -m venv venv3.8

Activamos el entorno virtual;

$ source venv3.8/bin/activate

Para desactivarlo:

$ deactivate

Utilizamos pip para gestionar los módulos en el entorno virtual:

$ pip list

Package       Version
------------- -------
pip           20.1.1
pkg-resources 0.0.0
setuptools    44.0.0

Django

Instalamos Django (última versión por defecto), instalará también algunas dependencias:

$ pip install django

Collecting django
  Downloading Django-3.1.2-py3-none-any.whl (7.8 MB)
     |████████████████████████████████| 7.8 MB 1.5 MB/s
Collecting sqlparse>=0.2.2
  Using cached sqlparse-0.3.1-py2.py3-none-any.whl (40 kB)
Collecting pytz
  Downloading pytz-2020.1-py2.py3-none-any.whl (510 kB)
     |████████████████████████████████| 510 kB 13.0 MB/s
Collecting asgiref~=3.2.10
  Using cached asgiref-3.2.10-py3-none-any.whl (19 kB)
Installing collected packages: sqlparse, pytz, asgiref, django
Successfully installed asgiref-3.2.10 django-3.1.2 pytz-2020.1 sqlparse-0.3.1

Nos quedará la siguiente lista de módulos instalados:

$ pip list

Package       Version
------------- -------
asgiref       3.2.10
Django        3.1.2
pip           20.1.1
pkg-resources 0.0.0
pytz          2020.1
setuptools    44.0.0
sqlparse      0.3.1

Si quisieramos instalar otro entorno virtual, ya sea en la misma máquina o en otra, podemos exportar la lista de módulos y sus versiones para recrear el entorno. Con la opción freeze de pip podemos obtener la lista y redirigir a un archivo, el que luego podemos utilizar para instalar los módulos en el nuevo entorno:

// guardar lista de módulos
$ pip freeze > requirements.txt

// instalar lista.
$ pip install -r requirements.txt

Proyecto1

Este ejemplo muestra el paso a paso (con Django ya instalado) la evolución de un primer proyecto.

Creación del proyecto

Al ubicarnos en la carpeta django para los proyectos antes creada tenemos hasta ahora:

$ ls -l
-rw-r--r-- 1 amvaldesj amvaldesj   59 Oct  6 09:35 requirements.txt
drwxr-xr-x 6 amvaldesj amvaldesj 4096 Oct  6 09:30 venv3.8

Creamos entonces en este nivel el proyecto que nombraremos proyecto1:

$ django-admin startproject proyecto1

Y la carpeta de trabajo nos queda:

$ ls -l
drwxr-xr-x 3 amvaldesj amvaldesj 4096 Oct  6 09:36 proyecto1
-rw-r--r-- 1 amvaldesj amvaldesj   59 Oct  6 09:35 requirements.txt
drwxr-xr-x 6 amvaldesj amvaldesj 4096 Oct  6 09:30 venv3.8

Ingresamos a la carpeta proyecto1 para trabajarlo:

$ cd proyecto1
$ ls -l
-rwxr-xr-x 1 amvaldesj amvaldesj  665 Oct  6 09:36 manage.py
drwxr-xr-x 2 amvaldesj amvaldesj 4096 Oct  6 09:36 proyecto1

Podemos probar como se ve hasta ahora ejecutando el script manager.py, el cual tiene múltiples opciones y una de ellas es levantar un servicio web local:

$ python manage.py runserver

Y abrimos en una navegador web la url http://127.0.0.1:8000/', debería aparecer una página de bienvenida y un cohete despegando... :D

Base de Datos

Las configuraciones de Django se realizan en el archivo settings.py, el que en nuestro ejemplo se encuentra proyecto1/settings.py'.

Si usamos alguna base de datos, se debe modificar las opciones del motor de base de datos a utilizar y que por defecto es sqlite. Vamos a usar esta por defecto.

   1 DATABASES = {
   2     'default': {
   3         'ENGINE': 'django.db.backends.sqlite3',
   4         'NAME': BASE_DIR / 'db.sqlite3',
   5     }
   6 }

Realizamos la carga inicial de la base de datos. Se crearan las tablas iniciales que requiere Django:

$ python manage.py migrate

Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying admin.0003_logentry_add_action_flag_choices... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying auth.0007_alter_validators_add_error_messages... OK
  Applying auth.0008_alter_user_username_max_length... OK
  Applying auth.0009_alter_user_last_name_max_length... OK
  Applying auth.0010_alter_group_name_max_length... OK
  Applying auth.0011_update_proxy_permissions... OK
  Applying auth.0012_alter_user_first_name_max_length... OK
  Applying sessions.0001_initial... OK

TIP Si modificamos/creamos modelos (Model) debemos primero preparar la migración com makemigrations y luego aplicar migrate:

$ python manage.py makemigrations
$ python manage.py migrate

Administración

Necesitamos en primer lugar crear un usuario que nos permita administrar Django. Creamos el usuario admin con clave admin:

$ python manage.py createsuperuser
Username (leave blank to use 'amvaldesj'): admin
Email address: admin@test.cl
Password:
Password (again):
The password is too similar to the username.
This password is too short. It must contain at least 8 characters.
This password is too common.
Bypass password validation and create user anyway? [y/N]: y
Superuser created successfully.

Levantamos el servidor local y visitamos el link: http://127.0.0.1:8000/admin

Creando una Aplicación

Hemos creado el proyecto1 sin embargo ahora debemos crear las aplicaciones que lo conformarán. Las aplicaciones ser pueden ver como diferentes módulos que son parte del proyecto. Creamos la aplicación principal:

$ python manage.py startapp principal

Debemos agregar esta aplicación en las configuraciones del proyecto para que sea reconocida (en settings.py):

   1 INSTALLED_APPS = [
   2     'django.contrib.admin',
   3     'django.contrib.auth',
   4     'django.contrib.contenttypes',
   5     'django.contrib.sessions',
   6     'django.contrib.messages',
   7     'django.contrib.staticfiles',
   8     'principal',
   9 ]

Los Templates

Django utiliza templates para generar las páginas resultantes en HTML, debemos configurar dónde estarán almacenados estos templates. Creamos una carpeta templates y luego la agregamos a las configuraciones en settings.py:

$ mkdir templates

   1 import os
   2 
   3 TEMPLATES = [
   4     {
   5         'BACKEND': 'django.template.backends.django.DjangoTemplates',
   6         'DIRS': [os.path.join(BASE_DIR, "templates")],
   7         'APP_DIRS': True,
   8         'OPTIONS': {
   9             'context_processors': [
  10                 'django.template.context_processors.debug',
  11                 'django.template.context_processors.request',
  12                 'django.contrib.auth.context_processors.auth',
  13                 'django.contrib.messages.context_processors.messages',
  14             ],
  15         },
  16     },
  17 ]

Creamos un template básico en templates/principal.html el cual iremos modificando más adelante:

   1 <html lang="en">
   2     <head>
   3         <meta charset="utf-8">
   4         <meta name="viewport" content="width=device-width, initial-scale=1">
   5         <meta name="description" content="">
   6         <meta name="author" content="">
   7         <title>{{ settings.APP_NAME }} {{ settings.APP_VERSION }}</title>
   8     </head>
   9 
  10     <body>
  11         <h1>Hola!</h1>
  12     </body>
  13 </html>

Podemos crear algunas variables en settings.py y que luego podemos utilizar en nuestros templates. El template anterior los utiliza para mostrar en el title de la página el nombre del proyecto y la versión (ver settings.APP_NAME y settings.APP_VERSION).

   1 APP_NAME = 'Proyecto'
   2 APP_VERSION = '0.1'

Rutas iniciales

En el archivo urls.py vamos a agregar las rutas que Django debe reconocer para direccionar a las vistas correspondientes. Vamos a modificar el archivo para que contenga las siguientes rutas. admin/ viene por defecto. Agregaremos una ruta para la página de inicio, en este caso la expresión regular r'^$' que corresponde a solicitar la raíz direcciona a la vista home, que luego debemos crear en views.py. Agregamos además el módulo url.

   1 from django.conf.urls import url
   2 from principal import views
   3 
   4 urlpatterns = [
   5     path('admin/', admin.site.urls),
   6     url(r'^$', views.home, name='home'),
   7 ]

Vista página inicial

Ya creadas las rutas debemos crear ahora la vista que se invocará cuando se solicita la página inicial. En el archivo views.py agregamos la vista home. Importamos además el módulo settings, el que se lo pasaremos al template que se retorna en la vista:

   1 from django.conf import settings
   2 
   3 # Create your views here.
   4 def home(request):
   5     return render(request, "principal.html", {'settings': settings})

Visualizamos la página: http://127.0.0.1:8000/

Creando modelos (Model)

Ya tenemos funcionando nuestro proyecto (la aplicación principal), ahora debemos modificar la base de datos incorporando las tablas (Modelos) necesarias para nuestra plataforma. Esta base de datos registrará información de mascotas y sus dueños. Para eso utilizaremos 3 modelos para representar las cardinalidades 1:N y N:M correspondientes. Este ejemplo mostrará paso a paso la incorporación de cada uno de estos modelos a la base de datos.

El Model Mascota (inicial)

Modelo inicial para Mascota (en models.py):

   1 class Mascota(models.Model):
   2     nombre = models.CharField(max_length=200)
   3     edad = models.IntegerField()

Preparamos la migración:

$ python manage.py makemigrations
Migrations for 'principal':
  principal/migrations/0001_initial.py
    - Create model Mascota

Aplicamos los cambios a la Base de datos:

$ python manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, principal, sessions
Running migrations:
  Applying principal.0001_initial... OK

Actualizamos el template principal.html y agregamos un link:

   1 <p><a href="/mascotas/">Mascotas</a></p>

Creamos la url para mascotas en urls.py:

   1 url(r'^mascotas/$', views.mascotas, name='mascotas'),

Necesitamos crear en views.py una vista que responderá por la ruta recién creada, en este caso views.mascotas. Necesitamos importar de models.py el modelo Mascota para poder usarlo y traer los objetos de este tipo que estén en la base de datos. Para obtener las mascotas se ejecuta el método Mascota.objects.all():

   1 from .models import Mascota
   2 
   3 def mascotas(request):
   4     # obtenemos las mascotas de la BD
   5     mascotas = Mascota.objects.all()
   6     # pasamos el resultado al template.
   7     return render(request, "mascotas.html", {'settings': settings, 'mascotas': mascotas})

En la vista anterior se hace referencia a un nuevo template mascotas.html que recibe en la llamada los objetos settings y mascotas. Tales objetos llevan información que en el template se mostrará. Se puede ver que se agregan algunos tags para indicar que hay instrucciones que se deben interpretar y ejecutar, es el caso de los tags if y for.

   1 <html lang="en">
   2     <head>
   3         <meta charset="utf-8">
   4         <meta name="viewport" content="width=device-width, initial-scale=1">
   5         <meta name="description" content="">
   6         <meta name="author" content="">
   7         <title>{{ settings.APP_NAME }} {{ settings.APP_VERSION }}</title>
   8     </head>
   9 
  10     <body>
  11         <h1>Mascotas!</h1>
  12 
  13         {% if mascotas %}
  14             <h1>Lista de Mascotas</h1>
  15             <ul>
  16                 {% for m in mascotas %}
  17                     <li>{{ m.nombre }} ({{ m.edad }})</li>
  18                 {% endfor %}
  19             </ul>
  20         {% else %}
  21             <h1>No hay Mascotas...</h1>
  22         {% endif %}
  23     </body>
  24 </html>

Probamos el link: http://127.0.0.1:8000/mascotas/

Agregar Mascotas desde la Shell de Django

Podemos utilizar esta shell para ingresar datos a la base de datos rápidamente y comprobar como funciona nuestra página. Debemos importar el Model que nos interesa, en este caso Mascota. Obtenemos las mascotas con Mascota.objects.all() y en este caso no hay ninguna. Luego, creamos un objeto Mascota(nombre='Pinina', edad=3) y lo guardamos en la base de datos con el método save().

En la terminal ejecutamos:

$ python manage.py shell
>>> from principal.models import Mascota
>>> mascotas =  Mascota.objects.all()
>>> mascotas
<QuerySet []>

>>> m = Mascota(nombre='Pinina', edad=3)
>>> m
<Mascota: Mascota object (None)>
>>> m.save()
>>> mascotas =  Mascota.objects.all()
>>> mascotas
<QuerySet [<Mascota: Mascota object (1)>]>

Probamos el link: http://127.0.0.1:8000/mascotas/

Agregar Mascotas desde la Administración de Django

Django provee desde la página de administración la posibilidad de poder gestionar la información de los modelos (datos de la base de datos) de una manera más amigable y rápida. Podemas agregar los modelos que necesitemos gestionar, por ejemplo el de Mascota. Los pasos son los siguientes:

  • editamos el archivo principal/admin.py e importamos el archivo dónde está la definción de los modelos y lo registramos para que Django lo reconozca.

   1 from .models import Mascota
   2 
   3 # Register your models here.
   4 admin.site.register(Mascota)
  • Luego ingresamos a la página de administración http://127.0.0.1:8000/admin/ y podemos ver que el modelo aparece disponible para su gestión (CRUD).

  • Podemos actualizar la definición del modelo Mascota para que se vea por defecto el nombre.

   1 class Mascota(models.Model):
   2     nombre = models.CharField(max_length=200)
   3     edad = models.IntegerField()
   4 
   5     def __str__(self):
   6         return self.nombre

mascotas_admin.png

El Model Persona (cardinalidad 1:N)

Vamos a crear el model Persona y consideraremos que una persona puede ser dueño de varias mascotas y que una mascota tiene (o no) un único dueño. Actualizamos el model Mascota para agregar como clave foranea el atributo dueno. El archivo models.py se vería algo así:

   1 class Persona(models.Model):
   2     nombre = models.CharField(max_length=200)
   3 
   4 class Mascota(models.Model):
   5     nombre = models.CharField(max_length=200)
   6     edad = models.IntegerField()
   7     dueno = models.ForeignKey(to=Persona, on_delete=models.SET_NULL, null=True)

Preparamos los cambios:

$ python manage.py makemigrations
Migrations for 'principal':
  principal/migrations/0002_auto_20201006_1531.py
    - Create model Persona
    - Add field dueno to mascota

Y los aplicamos a la base de datos:

$ python manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, principal, sessions
Running migrations:
  Applying principal.0002_auto_20201006_1531... OK

Actualizamos el template 'mascotas.html' para mostrar ahora el nombre del dueño de las mascotas:

   1 {% if mascotas %}
   2     <h1>Lista de Mascotas</h1>
   3     <ul>
   4         {% for m in mascotas %}
   5             <li>Nombre: {{ m.nombre }} edad: {{ m.edad }} dueño: {{ m.dueno.nombre }}</li>
   6         {% endfor %}
   7     </ul>
   8 {% else %}
   9     <h1>No hay Mascotas...</h1>
  10 {% endif %}

Agregar Persona y asociar a Mascota

Agregamos una persona, otra mascota y las asociamos desde la shell de Django:

$ python manage.py shell
>>> from principal.models import Mascota, Persona
>>> p = Persona(nombre='Alejandro')
>>> p
<Persona: Persona object (None)>
>>> m = Mascota(nombre='Pelusa', edad=1, dueno=p)
>>> p.save()
>>> p
<Persona: Persona object (1)>
>>> m.save()
>>> m
<Mascota: Mascota object (2)>

Probamos el link: http://127.0.0.1:8000/mascotas/

El Model Color (cardinalidad N:M)

Las mascotas pueden ser de varios colores y un color lo pueden tener más de una mascota. Creamos entonces el model Color y actualizamos el model Mascota que incorporará la relación Muchos a Muchos con la sentencia models.ManyToManyField(to=Color):

   1 class Color(models.Model):
   2     nombre = models.CharField(max_length=100)
   3 
   4 class Persona(models.Model):
   5     nombre = models.CharField(max_length=200)
   6 
   7 class Mascota(models.Model):
   8     nombre = models.CharField(max_length=200)
   9     edad = models.IntegerField()
  10     dueno = models.ForeignKey(to=Persona, on_delete=models.SET_NULL, null=True)
  11     colores = models.ManyToManyField(to=Color)

Preparamos los cambios para la base de datos:

$ python manage.py makemigrations
Migrations for 'principal':
  principal/migrations/0003_auto_20201006_1549.py
    - Create model Color
    - Add field colores to mascota

Y luego los aplicamos:

$ python manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, principal, sessions
Running migrations:
  Applying principal.0003_auto_20201006_1549... OK

Actualizamos el template mascotas.html para mostrar ahora los colores que pueda tener una mascota. También, mostramos el id de cada mascota (Django asigna este campo automáticamente como clave primaria a cada Model, a menos que explicitamente le indiquemos uno):

   1 {% if mascotas %}
   2     <h1>Lista de Mascotas</h1>
   3     <ul>
   4         {% for m in mascotas %}
   5             <li>
   6                 ID: {{ m.id }}
   7                 Nombre: {{ m.nombre }}
   8                 edad: {{ m.edad }}
   9                 dueño: {{ m.dueno.nombre }}
  10                 colores:
  11                 {% for color in m.colores.all %}
  12                     {{ color.nombre }}&nbsp;
  13                 {% endfor %}
  14             </li>
  15         {% endfor %}
  16     </ul>
  17 {% else %}
  18     <h1>No hay Mascotas...</h1>
  19 {% endif %}

Agregar Colores y asociar a Mascota

Desde la shell de Django creamos algunos colores y se los asociamos a la mascota con id=1. Obtenemos el objeto mascota con tal identificador mediante el método get() y el filtro correspondiente (Mascota.objects.get(id=1)):

$ python manage.py shell
>>> from principal.models import Mascota, Color
>>> m = Mascota.objects.get(id=1)
>>> m
<Mascota: Mascota object (1)>
>>> blanco = Color(nombre="Blanco")
>>> negro = Color(nombre="Negro")
>>> blanco.save()
>>> negro.save()
>>> m.colores.add(blanco)
>>> m.colores.add(negro)

Probamos el link: http://127.0.0.1:8000/mascotas/

Screenshots

Página principal:

proyecto1_0.png

Lista de mascotas:

proyecto1_1.png

Página de administración de Django:

proyecto1_2.png

Descargar proyecto1

proyecto1_django.zip

Proyecto1 - Autenticación

Vamos a utilizar la máquinaria que provee Django para la autenticación, permitiéndonos utilizar los usuarios que creemos desde la administración. Por ahora, esta actualización muestra cómo utilizar las características de django.contrib.auth.urls. Nos basamos en la página https://developer.mozilla.org/es/docs/Learn/Server-side/Django/Authentication para este ejemplo.

Registration template

Asumiendo que tenemos instalada y funcionando la versión anterior. Crearemos la carpeta registration bajo templates y en ella guardaremos el template login.html. La estructura del proyecto sería:

(venv3.8) amvaldesj@primate:proyecto1$ tree
.
├── db.sqlite3
├── manage.py
├── principal
│   ├── admin.py
│   ├── apps.py
│   ├── __init__.py
│   ├── migrations
│   │   ├── 0001_initial.py
│   │   ├── 0002_auto_20201006_1531.py
│   │   ├── 0003_auto_20201006_1549.py
│   │   ├── __init__.py
│   │   └── __pycache__
│   │       ├── 0001_initial.cpython-38.pyc
│   │       ├── 0002_auto_20201006_1531.cpython-38.pyc
│   │       ├── 0003_auto_20201006_1549.cpython-38.pyc
│   │       └── __init__.cpython-38.pyc
│   ├── models.py
│   ├── __pycache__
│   │   ├── admin.cpython-38.pyc
│   │   ├── __init__.cpython-38.pyc
│   │   ├── models.cpython-38.pyc
│   │   └── views.cpython-38.pyc
│   ├── tests.py
│   └── views.py
├── proyecto1
│   ├── asgi.py
│   ├── __init__.py
│   ├── __pycache__
│   │   ├── __init__.cpython-38.pyc
│   │   ├── settings.cpython-38.pyc
│   │   ├── urls.cpython-38.pyc
│   │   └── wsgi.cpython-38.pyc
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── requirements.txt
└── templates
    ├── mascotas.html
    ├── principal.html
    └── registration
        └── login.html

El contenido del template login.html se muestra a continuación. Se pueden ver varias validaciones que el mismo Django se encarga de realizar, además del formuario para el ingreso de las credenciales.

   1 <p></p>
   2 
   3 {% if form.errors %}
   4     <p>El usuario y/o clave son incorrectos, intente de nuevo.</p>
   5 {% endif %}
   6 
   7 {% if next %}
   8     {% if user.is_authenticated %}
   9         <p>Your account doesn't have access to this page. To proceed, please login with an account that has access.</p>
  10     {% else %}
  11         <p>Ingrese sus credenciales.</p>
  12     {% endif %}
  13 {% endif %}
  14 
  15 <form method="post" action="{% url 'login' %}">
  16 {% csrf_token %}
  17     <table>
  18     <tr>
  19         <td>{{ form.username.label_tag }}</td>
  20         <td>{{ form.username }}</td>
  21     </tr>
  22     <tr>
  23         <td>{{ form.password.label_tag }}</td>
  24         <td>{{ form.password }}</td>
  25     </tr>
  26     </table>
  27     <input type="submit" value="Ingresar" />
  28     <input type="hidden" name="next" value="{{ next }}" />
  29 </form>

Nuevas rutas accounts

Actualizamos el archivo urls.py para incluir las rutas para la autenticación (accounts). Agregamos también el módulo include que permite incluir un conjunto de rutas.

   1 from django.urls import path, include
   2 
   3 urlpatterns = [
   4     path('admin/', admin.site.urls),
   5     path('accounts/', include('django.contrib.auth.urls')),
   6     url(r'^$', views.home, name='home'),
   7     url(r'^mascotas/$', views.mascotas, name='mascotas'),
   8 ]

Rutas por defecto

Necesitamos indicar a Django algunas rutas por defecto para el manejo de la autenticación, qué rutas llamar para el login y el logout. Actualizamos el archivo settings.py. LOGIN_URL indica la ruta a llamar cuando se requiera autenticación, en este caso, Django cargar el template login.html antes creado. LOGIN_REDIRECT_URL indica la ruta a llamar luego de la autenticación exitosa, en este caso la página principal.

   1 LOGIN_URL = '/accounts/login'
   2 LOGIN_REDIRECT_URL = '/'

Decoradores (@login_required)

Ahora, necesitamos indicar qué vistas (en views.py) requieren de un usuario autenticado para poder ser ejecutadas. Vamos a agregar en views.py un decorador que nos permita explicitar estas vistas. Utilizamos para esto entonces el decorador @login_required. En nuestro ejemplo, tanto la página principal como el de las mascotas requiere de un usuario autenticado.

   1 from django.contrib.auth.decorators import login_required
   2 
   3 # Create your views here.
   4 @login_required
   5 def home(request):
   6     return render(request, "principal.html", {'settings': settings})
   7 
   8 @login_required
   9 def mascotas(request):
  10     # obtenemos las mascotas de la BD
  11     mascotas = Mascota.objects.all()
  12     # pasamos el resultado al template.
  13     return render(request, "mascotas.html", {'settings': settings, 'mascotas': mascotas})

Pruebas

Probamos el link: http://127.0.0.1:8000/ No debemos estar previamente autenticados en la página de administración de Django, si es así, cerramos la sessión. Deberíamos ver una página como la siguiente:

auten-1.png

Notar que la URL ha cambiado (Django redireccionó) a http://127.0.0.1:8000/accounts/login/?next=/ que es lo configurado en settings.py. Ingresamos las credenciales incorrectas admin con clave admin0 y debería mostrar la página indicando en problema:

auten1-2.png

Si intentamos acceder directamente a una ruta, por ejemplo http://127.0.0.1:8000/mascotas/, Django nos redirije a la página de login:

autn-1-3.png

Actualizamos los templates principal.html y mascotas.html y les agregamos algunos enlaces (para cerrr la sesión). En principal.html mostramos el nombre del usuario autenticado utilizando user.get_username.

principal.html

   1 <html lang="en">
   2     <head>
   3         <meta charset="utf-8">
   4         <meta name="viewport" content="width=device-width, initial-scale=1">
   5         <meta name="description" content="">
   6         <meta name="author" content="">
   7         <title>{{ settings.APP_NAME }} {{ settings.APP_VERSION }}</title>
   8     </head>
   9 
  10     <body>
  11         <p><a href="/mascotas/">Mascotas</a> | <a class="nav-link" href="{% url 'logout' %}?next=/"> Salir</a></p>
  12         <h1>Hola! <b>{{ user.get_username }}</b> </h1>
  13 
  14     </body>
  15 </html>

mascotas.html

   1 <html lang="en">
   2     <head>
   3         <meta charset="utf-8">
   4         <meta name="viewport" content="width=device-width, initial-scale=1">
   5         <meta name="description" content="">
   6         <meta name="author" content="">
   7         <title>{{ settings.APP_NAME }} {{ settings.APP_VERSION }}</title>
   8     </head>
   9 
  10     <body>
  11         <a class="nav-link" href="/">Home</a> | <a class="nav-link" href="{% url 'logout' %}?next=/"> Salir</a>
  12         <h1>Mascotas!</h1>
  13 
  14         {% if mascotas %}
  15             <h1>Lista de Mascotas</h1>
  16             <ul>
  17                 {% for m in mascotas %}
  18                     <li>
  19                         ID: {{ m.id }}
  20                         Nombre: {{ m.nombre }}
  21                         edad: {{ m.edad }}
  22                         dueño: {{ m.dueno.nombre }}
  23                         colores:
  24                         {% for color in m.colores.all %}
  25                             {{ color.nombre }}&nbsp;
  26                         {% endfor %}
  27                     </li>
  28                 {% endfor %}
  29             </ul>
  30         {% else %}
  31             <h1>No hay Mascotas...</h1>
  32         {% endif %}
  33     </body>
  34 </html>

Las correspondientes vistas serían:

auten-1-4.png
auten-1-5.png

django (última edición 2021-06-03 20:46:27 efectuada por AlejandroValdes)