Cómo crear modelos de Django

Introducción

En el tutorial anterior, “Cómo Crear una Aplicación Django y Conectarla a una Base de Datos,” cubrimos cómo crear una base de datos MySQL, cómo crear y comenzar una aplicación Django, y cómo conectarla a una base de datos MySQL.

En este tutorial, crearemos los modelos de Django que definen los campos y comportamientos de los datos de la aplicación Blog que estaremos almacenando. Estos modelos mapean los datos de su aplicación Django a la base de datos. Es lo que Django utiliza para generar las tablas de la base de datos a través de su API de mapeo objeto-relacional (ORM), conocida como “modelos.”

Requisitos Previos

Este tutorial es parte de la serie de Desarrollo Django y es una continuación de esa serie.

Si no has seguido esta serie, estamos haciendo las siguientes suposiciones:

Dado que este tutorial trata principalmente sobre los modelos de Django, es posible que puedas seguirlo incluso si tienes una configuración algo diferente.

Paso 1: Crear aplicación Django

Para ser coherentes con la filosofía de modularidad de Django, crearemos una aplicación Django dentro de nuestro proyecto que contenga todos los archivos necesarios para crear el sitio web del blog.

Cuando comencemos a trabajar en Python y Django, debemos activar nuestro entorno virtual de Python y dirigirnos al directorio raíz de nuestra aplicación. Si seguiste la serie, puedes lograrlo escribiendo lo siguiente.

  1. cd ~/my_blog_app
  2. . env/bin/activate
  3. cd blog

A partir de ahí, ejecutemos este comando:

  1. python manage.py startapp blogsite

Esto creará nuestra aplicación junto con un directorio blogsite.

En este punto de la serie de tutoriales, tendrás la siguiente estructura de directorios para tu proyecto:

my_blog_app/
└── blog
    ├── blog
    │   ├── __init__.py
    │   ├── __pycache__
    │   │   ├── __init__.cpython-38.pyc
    │   │   ├── settings.cpython-38.pyc
    │   │   ├── urls.cpython-38.pyc
    │   │   └── wsgi.cpython-38.pyc
    │   ├── asgi.py
    │   ├── settings.py
    │   ├── urls.py
    │   └── wsgi.py
    ├── blogsite
    │   ├── __init__.py
    │   ├── admin.py
    │   ├── apps.py
    │   ├── migrations
    │   │   └── __init__.py
    │   ├── models.py
    │   ├── tests.py
    │   └── views.py
    └── manage.py

El archivo en el que nos enfocaremos en este tutorial será el archivo models.py, que se encuentra en el directorio blogsite.

Paso 2 — Agregar el Modelo de Publicaciones

Primero, necesitamos abrir y editar el archivo models.py para que contenga el código para generar un modelo de Post. Un modelo de Post contiene los siguientes campos de la base de datos:

  • title — El título de la entrada del blog.
  • slug — Donde se almacenan y generan las URL válidas para las páginas web.
  • content — El contenido textual de la entrada del blog.
  • created_on — La fecha en la que se creó la entrada.
  • author — La persona que ha escrito la entrada.

Ahora, muévete al directorio donde se encuentra el archivo models.py.

  1. cd ~/my_blog_app/blog/blogsite

Usa el comando cat para mostrar el contenido del archivo en tu terminal.

  1. cat models.py

El archivo debería tener el siguiente código, que importa modelos, junto con un comentario que describe lo que se debe colocar en este archivo models.py.

models.py
from django.db import models

# Crea tus modelos aquí.

Usando tu editor de texto favorito, agrega el siguiente código al archivo models.py. Usaremos nano como nuestro editor de texto, pero puedes usar el que prefieras.

  1. nano models.py

Dentro de este archivo, el código para importar la API de modelos ya está añadido, así que podemos eliminar el comentario que sigue. Luego importaremos slugify para generar slugs a partir de cadenas, el User de Django para autenticación, y reverse de django.urls para brindarnos mayor flexibilidad al crear URLs.

models.py
from django.db import models
from django.template.defaultfilters import slugify
from django.contrib.auth.models import User
from django.urls import reverse

Después, agrega el método de clase en la clase del modelo que llamaremos Post, con los siguientes campos de la base de datos: title, slug, content, created_on y author. Agrega estos debajo de tus declaraciones de importación.

models.py
...
class Post(models.Model):
    title = models.CharField(max_length=255)
    slug = models.SlugField(unique=True, max_length=255)
    content = models.TextField()
    created_on = models.DateTimeField(auto_now_add=True)
    author = models.TextField()

A continuación, añadiremos funcionalidad para la generación de la URL y la función para guardar la publicación. Esto es crucial, porque crea un enlace único para que coincida con nuestra publicación única.

models.py
...
    def get_absolute_url(self):
        return reverse('blog_post_detail', args=[self.slug])

    def save(self, *args, **kwargs):
        if not self.slug:
            self.slug = slugify(self.title)
        super(Post, self).save(*args, **kwargs)

Ahora, necesitamos decirle al modelo cómo deberían ser ordenadas y mostradas las publicaciones en la página web. La lógica para esto se agregará a una clase Meta interna anidada. La clase Meta generalmente contiene otra lógica importante del modelo que no está relacionada con la definición de campos de la base de datos.

models.py
...
    class Meta:
        ordering = ['created_on']

        def __unicode__(self):
            return self.title

Finalmente, agregaremos el modelo Comment a este archivo. Esto implica agregar otra clase llamada Comment con models.Models en su firma y los siguientes campos de base de datos definidos:

  • name — El nombre de la persona que publica el comentario.
  • email — La dirección de correo electrónico de la persona que publica el comentario.
  • text — El texto del comentario en sí mismo.
  • post — La publicación con la que se hizo el comentario.
  • created_on — La hora en que se creó el comentario.
models.py
...
class Comment(models.Model):
    name = models.CharField(max_length=42)
    email = models.EmailField(max_length=75)
    website = models.URLField(max_length=200, null=True, blank=True)
    content = models.TextField()
    post = models.ForeignKey(Post, on_delete=models.CASCADE)
    created_on = models.DateTimeField(auto_now_add=True)

En este punto, el archivo models.py estará completo. Asegúrate de que tu archivo models.py coincida con el siguiente:

models.py
from django.db import models
from django.template.defaultfilters import slugify
from django.contrib.auth.models import User
from django.urls import reverse


class Post(models.Model):
    title = models.CharField(max_length=255)
    slug = models.SlugField(unique=True, max_length=255)
    content = models.TextField()
    created_on = models.DateTimeField(auto_now_add=True)
    author = models.TextField()

    def get_absolute_url(self):
        return reverse('blog_post_detail', args=[self.slug])
    
    def save(self, *args, **kwargs):
        if not self.slug:
            self.slug = slugify(self.title)
        super(Post, self).save(*args, **kwargs)

    class Meta:
        ordering = ['created_on']

        def __unicode__(self):
            return self.title


class Comment(models.Model):
    name = models.CharField(max_length=42)
    email = models.EmailField(max_length=75)
    website = models.URLField(max_length=200, null=True, blank=True)
    content = models.TextField()
    post = models.ForeignKey(Post, on_delete=models.CASCADE)
    created_on = models.DateTimeField(auto_now_add=True)


Asegúrate de guardar y cerrar el archivo. Si estás usando nano, puedes hacerlo escribiendo CTRL y X, luego Y, y luego ENTER.

Con el archivo models.py configurado, podemos continuar actualizando nuestro archivo settings.py.

Paso 3 — Actualizar la Configuración

Ahora que hemos agregado modelos a nuestra aplicación, debemos informar a nuestro proyecto de la existencia de la aplicación blogsite que acabamos de agregar. Hacemos esto agregándola a la sección INSTALLED_APPS en settings.py.

Navega hasta el directorio donde se encuentra tu archivo settings.py.

  1. cd ~/my_blog_app/blog/blog

Desde aquí, abre tu archivo settings.py, por ejemplo, con nano.

  1. nano settings.py

Con el archivo abierto, agrega tu aplicación blogsite a la sección INSTALLED_APPS del archivo, como se indica a continuación.

settings.py
# Definición de aplicaciones
INSTALLED_APPS = [
    'blogsite',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

Con la aplicación blogsite agregada, puedes guardar y salir del archivo.

En este punto, estamos listos para avanzar y aplicar estos cambios.

Paso 4 — Realizar migraciones

Con nuestros modelos Post y Comment agregados, el siguiente paso es aplicar estos cambios para que nuestro esquema de base de datos MySQL los reconozca y cree las tablas necesarias.

Primero, debemos empaquetar nuestros cambios de modelo en archivos de migración individuales usando el comando makemigrations. Estos archivos son similares a los commits en un sistema de control de versiones como Git.

Ahora, si navegas a ~/mi_aplicacion_de_blog/blog/blogsite/migrations y ejecutas ls, notarás que solo hay un archivo __init__.py. Esto cambiará una vez que agreguemos las migraciones.

Cambia al directorio del blog usando cd, así:

  1. cd ~/my_blog_app/blog

Luego ejecuta el comando makemigrations en manage.py.

  1. python manage.py makemigrations

Luego deberías recibir la siguiente salida en tu ventana de terminal:

Output
Migrations for 'blogsite': blogsite/migrations/0001_initial.py - Create model Post - Create model Comment

Recuerda, cuando navegamos a /~/my_blog_app/blog/blogsite/migrations y solo teníamos el archivo __init__.py? Si ahora volvemos a ese directorio, notaremos que se han añadido dos elementos: __pycache__ y 0001_initial.py. El archivo 0001_initial.py se generó automáticamente cuando ejecutaste makemigrations. Un archivo similar se generará cada vez que ejecutes makemigrations.

Ejecuta less 0001_initial.py desde el directorio en el que se encuentra si quieres leer lo que contiene el archivo.

Ahora navega a ~/my_blog_app/blog:

  1. cd ~/my_blog_app/blog

Dado que hemos creado un archivo de migración, debemos aplicar los cambios que describen estos archivos a la base de datos usando el comando migrate. Pero primero, comprobemos qué migraciones existen actualmente, utilizando el comando showmigrations.

  1. python manage.py showmigrations
Output
admin [X] 0001_initial [X] 0002_logentry_remove_auto_add [X] 0003_logentry_add_action_flag_choices auth [X] 0001_initial [X] 0002_alter_permission_name_max_length [X] 0003_alter_user_email_max_length [X] 0004_alter_user_username_opts [X] 0005_alter_user_last_login_null [X] 0006_require_contenttypes_0002 [X] 0007_alter_validators_add_error_messages [X] 0008_alter_user_username_max_length [X] 0009_alter_user_last_name_max_length [X] 0010_alter_group_name_max_length [X] 0011_update_proxy_permissions blogsite [ ] 0001_initial contenttypes [X] 0001_initial [X] 0002_remove_content_type_name sessions [X] 0001_initial

Notarás que todas las migraciones están marcadas excepto la de 0001_initial que acabamos de crear con los modelos Post y Comment.

Ahora veamos qué declaraciones SQL se ejecutarán una vez que realicemos las migraciones, utilizando el siguiente comando. Toma la migración y el título de la migración como argumento:

  1. python manage.py sqlmigrate blogsite 0001_initial

A continuación se revela la consulta SQL real que se realiza tras bambalinas.

Output
-- -- Crear modelo Post -- CREATE TABLE `blogsite_post` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `title` varchar(255) NOT NULL, `slug` varchar(255) NOT NULL UNIQUE, `content` longtext NOT NULL, `created_on` datetime(6) NOT NULL, `author` longtext NOT NULL); -- -- Crear modelo Comment -- CREATE TABLE `blogsite_comment` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `name` varchar(42) NOT NULL, `email` varchar(75) NOT NULL, `website` varchar(200) NULL, `content` longtext NOT NULL, `created_on` datetime(6) NOT NULL, `post_id` integer NOT NULL); ALTER TABLE `blogsite_comment` ADD CONSTRAINT `blogsite_comment_post_id_de248bfe_fk_blogsite_post_id` FOREIGN KEY (`post_id`) REFERENCES `blogsite_post` (`id`);

Ahora realicemos las migraciones para que se apliquen a nuestra base de datos MySQL.

  1. python manage.py migrate

Recibiremos la siguiente salida:

Output
Operations to perform: Apply all migrations: admin, auth, blogsite, contenttypes, sessions Running migrations: Applying blogsite.0001_initial... OK

Has aplicado tus migraciones con éxito.

Es importante tener en cuenta que hay tres advertencias con las migraciones de Django cuando se utiliza MySQL como backend, según lo establecido en la documentación de Django.

  • Falta de soporte para transacciones alrededor de operaciones de alteración de esquema. En otras palabras, si una migración no se aplica correctamente, tendrás que deshacer manualmente los cambios realizados para intentar otra migración. No es posible retroceder a un punto anterior antes de que se realizaran cambios en la migración fallida.
  • Para la mayoría de las operaciones de alteración de esquema, MySQL reescribirá completamente las tablas. En el peor de los casos, la complejidad temporal será proporcional al número de filas en la tabla para agregar o quitar columnas. Según la documentación de Django, esto podría ser tan lento como un minuto por cada millón de filas.
  • En MySQL, hay límites pequeños en la longitud de los nombres de columnas, tablas e índices. También hay un límite en el tamaño combinado de todas las columnas y cubiertas de índices. Mientras que otros backends pueden admitir límites más altos creados en Django, los mismos índices no se podrán crear con un backend de MySQL.

Para cada base de datos que consideres para usar con Django, asegúrate de evaluar las ventajas y desventajas de cada una.

Paso 5: Verificar el Esquema de la Base de Datos

Con las migraciones completas, debemos verificar la generación exitosa de las tablas de MySQL que hemos creado a través de nuestros modelos de Django.

Para hacer esto, ejecuta el siguiente comando en la terminal para iniciar sesión en MySQL. Utilizaremos el usuario djangouser que creamos en el tutorial anterior.

  1. mysql blog_data -u djangouser

Ahora, selecciona nuestra base de datos blog_data. Si no sabes qué base de datos estás usando, puedes mostrar todas las bases de datos con SHOW DATABASES; en SQL.

  1. USE blog_data;

Luego escribe el siguiente comando para ver las tablas.

  1. SHOW TABLES;

Esta consulta SQL debería revelar lo siguiente:

Output
+----------------------------+ | Tables_in_blog_data | +----------------------------+ | auth_group | | auth_group_permissions | | auth_permission | | auth_user | | auth_user_groups | | auth_user_user_permissions | | blogsite_comment | | blogsite_post | | django_admin_log | | django_content_type | | django_migrations | | django_session | +----------------------------+ 12 rows in set (0.01 sec)

Entre las tablas se encuentran blogsite_comment y blogsite_post. Estos son los modelos que acabamos de crear nosotros mismos. Verifiquemos que contengan los campos que hemos definido.

  1. DESCRIBE blogsite_comment;
Output
+------------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +------------+--------------+------+-----+---------+----------------+ | id | int | NO | PRI | NULL | auto_increment | | name | varchar(42) | NO | | NULL | | | email | varchar(75) | NO | | NULL | | | website | varchar(200) | YES | | NULL | | | content | longtext | NO | | NULL | | | created_on | datetime(6) | NO | | NULL | | | post_id | int | NO | MUL | NULL | | +------------+--------------+------+-----+---------+----------------+ 7 rows in set (0.00 sec)
  1. DESCRIBE blogsite_post;
Output
+------------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +------------+--------------+------+-----+---------+----------------+ | id | int | NO | PRI | NULL | auto_increment | | title | varchar(255) | NO | | NULL | | | slug | varchar(255) | NO | UNI | NULL | | | content | longtext | NO | | NULL | | | created_on | datetime(6) | NO | | NULL | | | author | longtext | NO | | NULL | | +------------+--------------+------+-----+---------+----------------+ 6 rows in set (0.00 sec)

Hemos verificado que las tablas de la base de datos se generaron correctamente a partir de las migraciones de modelos de Django.

Puedes salir de MySQL con CTRL + D y cuando estés listo para salir de tu entorno de Python, puedes ejecutar el comando deactivate:

  1. deactivate

Desactivar tu entorno de programación te devolverá al indicador de comando de la terminal.

Conclusión

En este tutorial, hemos añadido con éxito modelos para funcionalidades básicas en una aplicación web de blog. Has aprendido cómo codificar modelos, cómo funcionan las migraciones y el proceso de traducir los modelos de Django a tablas de base de datos MySQL reales.

Source:
https://www.digitalocean.com/community/tutorials/how-to-create-django-models