Diferencias entre las revisiones 2 y 20 (abarca 18 versiones)
Versión 2 con fecha 2020-10-06 16:31:34
Tamaño: 481
Comentario:
Versión 20 con fecha 2020-10-06 21:03:10
Tamaño: 12937
Comentario:
Los textos eliminados se marcan así. Los textos añadidos se marcan así.
Línea 5: Línea 5:
Homepage: https://www.djangoproject.com/
Línea 6: Línea 8:
=== Preparando el entorno virtual ===

*
Instalar módulo para crear entornos virtuales en Python (3):
=== Preparando el entorno de trabajo ===
Instalar módulo para crear entornos virtuales en Python (3):
Línea 13: Línea 14:

*
Creamos una carpeta para crear nuestros proyectos Django.
Creamos una carpeta para crear nuestros proyectos Django.
Línea 20: Línea 20:

*
Creamos un entorno virtual para Python 3.8 (dependerá la versión que tengan instalada):
Creamos un entorno virtual para Python 3.8 (dependerá la versión que tengan instalada):
Línea 26: Línea 25:
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.

{{{
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / 'db.sqlite3',
    }
}
}}}
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):

{{{
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'principal',
]
}}}
== 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
}}}
{{{
import os

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, "templates")],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]
}}}
Creamos un template básico en '''templates/principal.html''' el cual iremos modificando más adelante:

{{{
<html lang="en">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <meta name="description" content="">
        <meta name="author" content="">
        <title>{{ settings.APP_NAME }} {{ settings.APP_VERSION }}</title>
    </head>

    <body>
        <h1>Hola!</h1>
    </body>
</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''').

{{{
APP_NAME = 'Proyecto'
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'''.

{{{
from django.conf.urls import url
from principal import views

urlpatterns = [
    path('admin/', admin.site.urls),
    url(r'^$', views.home, name='home'),
]
}}}
== 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:

{{{
from django.conf import settings

# Create your views here.
def home(request):
    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.

=== Mascota (Model) inicial ===
Modelo inicial para Mascota (en '''models.py'''):

{{{
class Mascota(models.Model):
    nombre = models.CharField(max_length=200)
    edad = models.IntegerField()
}}}
Preparamoos 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:

{{{
<p><a href="/mascotas/">Mascotas</a></p>
}}}
Creamos la url para mascotas en '''urls.py''':

{{{
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()''':

{{{
from .models import Mascota

def mascotas(request):
    # obtenemos las mascotas de la BD
    mascotas = Mascota.objects.all()
    # pasamos el resultado al template.
    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'''.

{{{
<html lang="en">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <meta name="description" content="">
        <meta name="author" content="">
        <title>{{ settings.APP_NAME }} {{ settings.APP_VERSION }}</title>
    </head>

    <body>
        <h1>Mascotas!</h1>

        {% if mascotas %}
            <h1>Lista de Mascotas</h1>
            <ul>
                {% for m in mascotas %}
                    <li>{{ m.nombre }} ({{ m.edad }})</li>
                {% endfor %}
            </ul>
        {% else %}
            <h1>No hay Mascotas...</h1>
        {% endif %}
    </body>
</html>
}}}

Primeros pasos con Django

Introducción:

Homepage: https://www.djangoproject.com/

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.

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / 'db.sqlite3',
    }
}

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):

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'principal',
]

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

import os

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, "templates")],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

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

<html lang="en">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <meta name="description" content="">
        <meta name="author" content="">
        <title>{{ settings.APP_NAME }} {{ settings.APP_VERSION }}</title>
    </head>

    <body>
        <h1>Hola!</h1>
    </body>
</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).

APP_NAME = 'Proyecto'
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.

from django.conf.urls import url
from principal import views

urlpatterns = [
    path('admin/', admin.site.urls),
    url(r'^$', views.home, name='home'),
]

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:

from django.conf import settings

# Create your views here.
def home(request):
    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.

Mascota (Model) inicial

Modelo inicial para Mascota (en models.py):

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

Preparamoos 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:

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

Creamos la url para mascotas en urls.py:

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():

from .models import Mascota

def mascotas(request):
    # obtenemos las mascotas de la BD
    mascotas = Mascota.objects.all()
    # pasamos el resultado al template.
    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.

<html lang="en">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <meta name="description" content="">
        <meta name="author" content="">
        <title>{{ settings.APP_NAME }} {{ settings.APP_VERSION }}</title>
    </head>

    <body>
        <h1>Mascotas!</h1>

        {% if mascotas %}
            <h1>Lista de Mascotas</h1>
            <ul>
                {% for m in mascotas %}
                    <li>{{ m.nombre }} ({{ m.edad }})</li>
                {% endfor %}
            </ul>
        {% else %}
            <h1>No hay Mascotas...</h1>
        {% endif %}
    </body>
</html>

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