Modelos en Django: qué son, cómo crearlos y usarlos paso a paso

Video thumbnail

Cuando empecé con Django, lo que más me sorprendió fue su forma de manejar la base de datos a través de los modelos. Si vienes de PHP, como fue mi caso, y has trabajado con frameworks como Laravel o CodeIgniter, notarás una gran diferencia: en Django puedes centralizar toda la definición de tus tablas en un único archivo y mantener un control limpio sobre la estructura de tus datos.

En este artículo te cuento qué son los modelos en Django, cómo se crean paso a paso y cómo aprovecharlos para estructurar tu base de datos de forma profesional.

Partimos de como mostrar un Hola Mundo en Django.

Qué es un modelo en Django y por qué es tan importante

Un modelo es una de las capas más potentes del patrón MTV (Model–Template–View).
Representa la estructura y el comportamiento de los datos con los que trabaja tu aplicación. En términos simples, cada modelo equivale a una tabla de base de datos y cada atributo de la clase es una columna.

En Django, el modelo es tu “ventana” hacia la base de datos: define cómo se guardan los datos, cómo se relacionan y cómo puedes consultarlos usando el ORM (Object Relational Mapper) sin escribir ni una línea de SQL.

El modelo como parte del patrón MTV

El modelo es la “M” del MTV. Se encarga de:

  • Estructurar los datos (campos y tipos).
  • Gestionar relaciones entre entidades.
  • Controlar la lógica de negocio (a través de métodos).

Cómo Django convierte una clase en una tabla

Cuando defines una clase en models.py y ejecutas una migración, Django genera automáticamente la tabla correspondiente en tu base de datos. Este proceso es el corazón del ORM.

Los modelos y el archivo único de la aplicación en Django

Para crear un modelo, obviamente necesitamos tener un proyecto y aplicación en Django cosa que ya hicimos anteriormente, en la aplicación llamada:

firstProject

Tenemos un archivo llamado models.py que esta completamente vacío; como puedes deducir por el nombre del archivo, sirve para almacenar o definir TODOS los modelos de esta aplicación, por lo tanto si vienes de PHP como yo, esto te puede chocar un poco ya que en frameworks populares como CodeIgniter o Laravel, nosotros definimos un modelo por clase, es decir, en un modelo solamente tenemos almacenados una clase y listo; pero en Django, específicamente en Python esto no es así y esto es muy bueno.

Una ventaja enorme que tenemos al crear clases como modelos o formularios en Django es que podemos definir todas las estructuras es decir, las clases en un solo archivo, por lo tanto podemos tener un gran control sobre cada una de las capas o subcapas de nuestro proyecto.

Y esto se debe a la gran modularización y organización al momento de importar una clase, función o variable desde Python.

Cómo crear un modelo en Django

Finalmente vamos a crear un modelo; un modelo simplemente es una clase en Python que define atributos en donde cada atributo es generalmente un campo de nuestro objeto que esto más adelante se va a traducir como una columna en base de datos, pero ya llegaremos a esto.

Tipos de campos

Tenemos múltiples tipos de campos que podemos emplear, para tipo texto, números, booleanos archivos, imágenes  y un largo etc:

Puedes ver más en la documentación oficial

Así que, finalmente vamos a crear un modelo por ejemplo uno que creamos en nuestro gran curso sobre Django que luzca de la siguiente manera:

class Comment(models.Model):
    text = models.TextField()
    date_posted = models.DateTimeField(auto_now_add=True)
    element = models.ForeignKey(Element, related_name='comments', on_delete=models.CASCADE, NULL=True)
 
    def __str__(self):
        return 'Comentario #{}'.format(self.id)

Explicación del código anterior

Entonces, tenemos una propiedad para el texto del comentario y una fecha, así de simple; pero como puedes ver, le podemos definir también atributos en los campos, que dependiendo del tipo de campo podemos definir unos u otros atributos u opciones, como es en caso de auto_now_add que recibe un booleano para indicar que apenas creemos este registro en la base de datos tome la fecha actual del sistema.

Como puedes ver, simplemente tenemos que especificar el tipo campo con la función correspondiente, por ejemplo TextField para un campo abierto de texto, o un campo DateTimeField para un campo de fecha, especificamos el nombre de la columna que sería el mismo nombre del atributo y listo.

Y con esto creamos nuestro primer modelo en Django; en las próximas entradas veremos qué más podemos hacer con este nuevo elemento en Django.

También especificamos el tipo de relación que en este caso es de tipo cascade.

Los modelos son la fuente única y definitiva de información sobre sus datos. Contiene los campos y comportamientos esenciales de los datos que está almacenando (la lógica de negocios). Generalmente, cada modelo se asigna a una sola tabla de base de datos y es una de las capas de nuestro MTV.

Y, en definitiva, son la capa que permite acceder a la base de datos y es la única entrada a la misma; cada aplicación en Django puede tener cero o más modelos, todos ellos viven dentro del archivo llamado models.py que se encuentra definido en cada aplicación.

Un modelo no es más que una clase, en donde, dicha clase va a ser reflejado en la base de datos a una tabla; es decir, una clase modelo (entiéndase una clase que está definida dentro del archivos models.py) va a corresponder a una tabla en la base de datos.

Importante señalar que, para crear las tablas correspondientes en la base de datos, es necesario ejecutar un comando, pero eso lo veremos luego.

Crear modelos

Los modelos forman parte de las aplicaciones en Django; dentro del archivo llamado models.py tal cual indica su nombre, podemos definir todos los modelos que se van a usar en la aplicación u otras aplicaciones mediante las importaciones.

Esto último, lo puedes constatar en la descripción de los models.py

# Crea tus modelos aquí.

Caso práctico

Dentro de la aplicación que creamos anteriormente, vamos a crear las siguientes clases:

elements/models.py

from django.db import models
# Create your models here.
class Category(models.Model):
    title = models.CharField(max_length=255)
    slug = models.SlugField(max_length=255)
    def __str__(self):
        return self.title
class Type(models.Model):
    title = models.CharField(max_length=255)
    slug = models.SlugField(max_length=255)
    def __str__(self):
        return self.title
class Element(models.Model):
    title = models.CharField(max_length=255)
    slug = models.SlugField(max_length=255,blank=True)
    description = models.TextField()
    price = models.DecimalField(max_digits=10,decimal_places=2, default=6.10) # 12345678.10
    category = models.ForeignKey(Category, on_delete=models.CASCADE)
    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)
    type = models.ForeignKey(Type, on_delete=models.CASCADE)

Explicación del código anterior

En uno de mis proyectos, usé tres modelos principales: Category, Type y Element.

Cada uno representa una entidad del sistema, y su estructura permite escalar fácilmente.

Aquí ya puedes empezar a ver las maravillas de Python; sintaxis limpia, expresiva y seguramente ya entiendas al menos en buena medida qué es lo que estamos definiendo.

Lo primero que hacemos es importar la clase Model de Django:

from django.db import models
***
models.Model

Luego, creamos clases que hereda de la importación anterior:

class Category(models.Model):
   ***
class Type(models.Model):
   ***
class Element(models.Model):
   ***

Dotando a dichas clases de ciertas características que iremos viendo poco a poco, que en este caso muy particular sería para manejar los modelos, incluyendo las conexiones a la base de datos y mapeo de dichas clases a la base de datos mediante las migraciones.

Luego, cada una de las propiedades anteriores definida en dicha clase, conforman la estructura de la entidad que queremos crear; en este caso categorías, tipos y elementos.

Aquí en este archivo elements/models.py, creamos tres modelos diferentes, dos de ellos son simples y son para la categoría y el tipo y el tercero es un poco más elaborado cuya intención es que pueda registrar publicaciones; publicaciones que pueden ser un post, curso o cualquier otra tipificación que quieras usar; el término de "element" se usa en el libro para colocar un nombre neutro para cada uno de estos tipos o clasificaciones.

Vamos a desfragmentar la clase de Element; entendiendo sus columnas, entenderás el de las otras dos clases y definiciones similares:

  • Con models.CharField(max_length=255) para la propiedad title, definimos un campo de tipo texto (CharField) el cual permite almacenar caracteres, con un atributo para limitar el tamaño máximo de 255 caracteres (max_length).
  • Con models.SlugField(max_length=255,blank=True) para la propiedad slug, definimos un campo de tipo SlugField, el cual permite almacenar solamente, letras, números y guiones que es ideal para manejar las URLs limpias o slug.
    • Con el blank indicamos que puede almacenar valores en blanco.
  • Con models.DecimalField(max_digits=10,decimal_places=2, default=6.10) para la propiedad price, indicamos un campo de tipo de decimal de una longitud de 10 dígitos como máximo y dos partes decimales con un valor por defecto de 6.10.
  • Con models.ForeignKey(<Relacion>, on_delete=models.CASCADE) Crearemos una relación foránea de tipo en cascada, con la categoría y tipo.
  • Para models.TextField() para la propiedad description, definimos un campo de tipo texto; esto es ideal para guardar grandes cantidades de texto.
  • Para los campos de fecha para created y updated que representan las fechas de creación y actualización de registros respectivamente, indicamos el campo de tipo DateTimeField que con el atributo de auto_now_add indicamos que puede establezca una fecha al generar el objeto y con el auto_now indicamos qué al guardar el objeto, coloque la fecha actual.

El porqué de esta estructura se debe a una publicación de cualquier tipo en el mundo real, si quieres crear una publicación, los elementos básicos son un título y contenido; generalmente le indicamos un resumen o descripción, y por supuestos unas fechas de controles son siempre bienvenidas; finalmente, al tener muchos posts de diversos tipos, le agregamos clasificaciones como indicamos anteriormente.

A la final, es importante que te familiarices con los tipos de columnas y atributos para emplear los que más de adapten a tus necesidades:

https://docs.djangoproject.com/en/dev/ref/models/fields/#field-types

Migraciones: reflejar tus modelos en la base de datos

Una vez definidos los modelos, el siguiente paso es crear las tablas en la base de datos.

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

Estos comandos generan y aplican los scripts necesarios.

En una ocasión olvidé ejecutar makemigrations antes de modificar un modelo, y terminé con errores de sincronización. Desde entonces, siempre hago un control de versiones de mis migraciones.

Consejo: evita eliminar campos directamente sin migrar antes; podrías perder datos valiosos.

Cómo registrar y probar tus modelos en el panel de administración

Django facilita la gestión de datos gracias a su admin panel.
Solo debes registrar tus modelos en admin.py:

from django.contrib import admin
from .models import Category, Type, Element
admin.site.register(Category)
admin.site.register(Type)
admin.site.register(Element)

Al ingresar a /admin, verás tus modelos listos para crear, editar o eliminar registros desde una interfaz gráfica.

⚠️ Errores comunes y buenas prácticas

  • Olvidar el null=True en relaciones opcionales.
  • No definir __str__(): sin este método, tus registros se verán como objetos genéricos.
  • Modificar campos sin generar migraciones previas.

En mi experiencia, lo mejor es mantener los modelos simples al inicio y refactorizar cuando la estructura del proyecto esté clara. Django es muy flexible con los cambios si migras correctamente.

Si vienes de frameworks como Laravel, te encantará ver cómo Django simplifica la gestión de esquemas sin romper compatibilidad.

El método __str__ en los modelos para imprimir una representación en texto del modelo/clase

Lo siguiente que vamos a ver es una característica que nos permite representar un objeto como un String y el mismo es el método llamado Str.

Ya que si intentamos imprimir desde un template o empleando la función print un objeto que pertenezca a un modelo (o clase en general); veremos que aparecerá algo como lo siguiente:

Comment object (1)

En donde el Comment es el nombre del modelo y el (1) es el identificador en la base de datos.

Ahora bien, nosotros podemos representar un modelo de Django como si fuera un simple texto; realmente este es una característica que nos ofrece Python y no Django, que es poder representar un objeto como si fuera un string; por lo tanto cuando hacemos el print de este objeto básicamente va a aparecer la representación que definamos en la función Str; por ejemplo, para nuestro modelo:

class Comment(models.Model):
    text = models.TextField()
    date_posted = models.DateTimeField(auto_now_add=True)
    element = models.ForeignKey(Element, related_name='comments', on_delete=models.CASCADE, NULL=True)
 
    def __str__(self):
        return 'Comentario #{}'.format(self.id) 

Aquí nosotros podemos acceder a todos los atributos y métodos del modelo que contenga a dicha función; y este método es empleado internamente por Python para  representar dicha instancia de una clase mediante un string al momento de imprimir el texto.

Y si imprimimos el siguiente objeto:

print(elements[0])

Al hacer un print: 

Comentario #1

Aparecerá el texto que configuramos anteriormente; esto lo puedes emplear para Ada vez que tengas una clases y en algún punto la quieras imprimir, ya se mediante la función de print o desde el template de Django.

Conclusión: por qué los modelos son el corazón de Django

Los modelos son la base de todo proyecto Django.
Te permiten manejar datos, relaciones y lógica de negocio sin preocuparte por SQL. Además, el ORM de Django traduce tus clases en consultas eficientes y seguras.

Cuando entendí esto, dejé de pensar en Django como un framework más y empecé a verlo como una herramienta completa de desarrollo estructurado.

❓ Preguntas frecuentes (FAQ)

1. ¿Qué diferencia hay entre un modelo y una migración?
El modelo define la estructura en Python; la migración crea o modifica la tabla en la base de datos.

2. ¿Cómo relacionar modelos entre sí?
Mediante campos como ForeignKey, OneToOneField o ManyToManyField.

3. ¿Dónde se define el archivo models.py?
En cada aplicación Django, dentro de su carpeta principal.

4. ¿Qué comando se usa para aplicar las migraciones?
python manage.py migrate

El siguiente paso consiste en conocer cómo puedes cambiar la base de datos a MySQL.

Acepto recibir anuncios de interes sobre este Blog.

Vamos a ver como podemos crear un modelo en Django, que recuerda es una de las capas del MTV de nuestra aplicación y la encargada de manejar los datos de la misma; ademas veremos como definir distintos campos.

| 👤 Andrés Cruz

🇺🇸 In english