Un modelo es la fuente única, definitiva de información sobre tus datos. Contiene los campos y comportamientos esenciales de los datos que estás almacenando. Generalmente, cada modelo se mapea a una sola tabla de base de datos.
Los fundamentos:
Cada modelo es una clase Python que hereda de django.db.models.Model.
Cada atributo del modelo representa un campo de la base de datos.
Con todo esto, Django te proporciona una API de acceso a la base de datos generada automáticamente; véase Haciendo consultas.
Este ejemplo de modelo define un Person, que tiene un first_name y un last_name.
from django.db import models
class Person(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
first_name y last_name son campos del modelo. Cada campo se especifica como una atributo de clase, y cada atributo se mapea con una columna de la base de datos.
La tabla de la base de datos creada por el modelo Person sería como esta:
CREATE TABLE myapp_person (
"id" bigint NOT NULL PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY,
"first_name" varchar(30) NOT NULL,
"last_name" varchar(30) NOT NULL
);
Algunos notas técnicas:
El nombre de la tabla, myapp_person, se deriva automáticamente de algunos metadatos del modelo pero puede ser sobrescrito. Consulta Nombres de tabla para obtener más detalles.
Se agrega automáticamente un campo id, pero se puede sobreescribir este comportamiento. Consulta la sección sobre campos de clave primaria automáticos.
El SQL CREATE TABLE en este ejemplo se formatea utilizando la sintaxis de PostgreSQL, pero es importante tener en cuenta que Django utiliza SQL adaptado al motor de base de datos especificado en tu archivo de configuración <topics/settings>.
Una vez que hayas definido tus modelos, necesitarás decirle a Django que vas a utilizar esos modelos. Hazlo editando tu archivo de configuración y cambiando la configuración INSTALLED_APPS para agregar el nombre del módulo que contiene tu models.py.
Ejemplo: si los modelos de tu aplicación viven en el módulo myapp.models (la estructura de paquete que se crea para una aplicación mediante el script manage.py startapp), INSTALLED_APPS debería leerse, en parte:
INSTALLED_APPS = [
# ...
"myapp",
# ...
]
When agregues nuevas aplicaciones a INSTALLED_APPS, asegúrate de ejecutar manage.py migrate, opcionalmente creando migraciones para ellas primero con manage.py makemigrations.
La parte más importante de un modelo – y la única parte requerida de un modelo – es la lista de campos de base de datos que define. Los campos se especifican mediante atributos de clase. Ten cuidado al elegir nombres de campo que no conflicten con la API de modelos como clean, save o delete.
Ejemplo:
from django.db import models
class Musician(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
instrument = models.CharField(max_length=100)
class Album(models.Model):
artist = models.ForeignKey(Musician, on_delete=models.CASCADE)
name = models.CharField(max_length=100)
release_date = models.DateField()
num_stars = models.IntegerField()
Cada campo en tu modelo debe ser una instancia del tipo de clase de campo adecuado. Django utiliza los tipos de clase de campo para determinar varias cosas:
El tipo de columna, que indica al motor de base de datos qué tipo de datos almacenar (por ejemplo INTEGER, VARCHAR, TEXT).
El widget HTML por defecto :doc:` </ref/forms/widgets>` a utilizar cuando se renderice un campo de formulario (por ejemplo <input type="text">, <select>).
Los requisitos de validación mínimos, utilizados en la interfaz administrativa de Django y en las formas generadas automáticamente.
Django incluye docenas de tipos de campos integrados; puedes encontrar la lista completa en la referencia de campos de modelo. Puedes escribir fácilmente tus propios campos si los integrados de Django no funcionan como necesitas; consulta Cómo crear campos de modelo personalizados.
Cada campo toma un conjunto de argumentos específicos del campo (documentados en la referencia de campos de modelo). Por ejemplo, CharField (y sus subclases) requieren el argumento max_length, que especifica el tamaño del campo VARCHAR de base de datos utilizado para almacenar los datos.
También hay un conjunto de argumentos comunes disponibles para todos los tipos de campos. Todos son opcionales. Se explican detalladamente en la referencia, pero aquí tienes una breve descripción de los más utilizados:
nullSi True, Django almacenará valores vacíos como NULL en la base de datos. El valor por defecto es False.
blankSi True, el campo se permite estar en blanco. El valor por defecto es False.
Ten en cuenta que esto es diferente a null. null es puramente relacionado con la base de datos, mientras que blank es relacionado con la validación. Si un campo tiene blank=True, la validación de formularios permitirá la entrada de un valor vacío. Si un campo tiene blank=False, el campo será requerido.
choicesUna secuencia de pares de tuplas con 2 valores, una mappings, un tipo de enumeración (referencia a tipos de enumeración), o una función callable (que no espera argumentos y devuelve cualquiera de los formatos anteriores), para utilizar como opciones para este campo. Si se proporciona, el widget de formulario por defecto será un cuadro desplegable en lugar del campo de texto estándar y limitará las opciones a las dadas.
Una lista de opciones choices se ve así:
YEAR_IN_SCHOOL_CHOICES = [
("FR", "Freshman"),
("SO", "Sophomore"),
("JR", "Junior"),
("SR", "Senior"),
("GR", "Graduate"),
]
Nota
Se crea una nueva migración cada vez que cambia el orden de choices.
El primer elemento en cada tupla es el valor que se almacenará en la base de datos. El segundo elemento se muestra mediante el widget de formulario del campo.
Dado un instancia de modelo, el valor de visualización para un campo con choices se puede acceder utilizando el método get_FOO_display().
Ejemplo:
from django.db import models
class Person(models.Model):
SHIRT_SIZES = {
"S": "Small",
"M": "Medium",
"L": "Large",
}
name = models.CharField(max_length=60)
shirt_size = models.CharField(max_length=1, choices=SHIRT_SIZES)
>>> p = Person(name="Fred Flintstone", shirt_size="L")
>>> p.save()
>>> p.shirt_size
'L'
>>> p.get_shirt_size_display()
'Large'
También puedes utilizar clases de enumeración para definir choices de manera concisa:
from django.db import models
class Runner(models.Model):
MedalType = models.TextChoices("MedalType", "GOLD SILVER BRONZE")
name = models.CharField(max_length=60)
medal = models.CharField(blank=True, choices=MedalType, max_length=10)
Están disponibles más ejemplos en la referencia del campo de modelo: model field reference.
defaultEl valor por defecto del campo. Esto puede ser un valor o un objeto callable. Si es llamable se llamará cada vez que se crea una nueva instancia.
db_defaultEl valor por defecto calculado en la base de datos para el campo. Esto puede ser un valor literal o una función de la base de datos.
Si tanto db_default como Field.default están configurados, default tendrá prioridad al crear instancias en código Python. db_default seguirá estando configurado a nivel de base de datos y se utilizará cuando se inserten filas fuera del ORM o cuando se agregue un nuevo campo en una migración.
help_textTexto adicional de ayuda para ser mostrado con el widget de formulario. Es útil incluso si tu campo no está siendo utilizado en un formulario.
primary_keySi True, este campo es la clave primaria del modelo.
Si no especificas primary_key=True para ningún campo de tu modelo, Django agregará automáticamente un campo para contener la clave primaria, por lo que no necesitas establecer primary_key=True en ninguno de tus campos a menos que quieras sobreescribir el comportamiento predeterminado de la clave primaria. Para más información, consulta campos de clave primaria automáticos.
El campo de clave primaria es de solo lectura. Si cambias el valor de la clave primaria en un objeto existente y luego lo guardas, se creará un nuevo objeto junto al antiguo. Por ejemplo:
from django.db import models
class Fruit(models.Model):
name = models.CharField(max_length=100, primary_key=True)
>>> fruit = Fruit.objects.create(name="Apple")
>>> fruit.name = "Pear"
>>> fruit.save()
>>> Fruit.objects.values_list("name", flat=True)
<QuerySet ['Apple', 'Pear']>
uniqueSi True, este campo debe ser único a lo largo de la tabla.
Nuevamente, estos son solo descripciones breves de las opciones de campos más comunes. Puedes encontrar detalles completos en referencia de opciones de campos de modelo común.
Por defecto, Django asigna a cada modelo una clave primaria autoincremental con el tipo especificado por aplicación en AppConfig.default_auto_field o globalmente en la configuración DEFAULT_AUTO_FIELD. Por ejemplo:
id = models.BigAutoField(primary_key=True)
Si deseas especificar una clave primaria personalizada, especifica primary_key=True en uno de tus campos. Si Django ve que has establecido explícitamente Field.primary_key, no agregará la columna id automática.
Cada modelo requiere exactamente un campo con primary_key=True (ya sea declarado explícitamente o agregado automáticamente).
Cada tipo de campo, excepto para ForeignKey, ManyToManyField y OneToOneField, admite un argumento posicional opcional – un nombre verbal. Si no se da el nombre verbal, Django creará automáticamente uno utilizando el nombre del atributo del campo, convirtiendo los guiones bajos en espacios.
En este ejemplo, el nombre verbal es "nombre de persona":
first_name = models.CharField("person's first name", max_length=30)
En este ejemplo, el nombre verbal es "nombre":
first_name = models.CharField(max_length=30)
ForeignKey, ManyToManyField y OneToOneField requieren que el primer argumento sea una clase de modelo, así que utiliza la palabra clave verbose_name:
poll = models.ForeignKey(
Poll,
on_delete=models.CASCADE,
verbose_name="the related poll",
)
sites = models.ManyToManyField(Site, verbose_name="list of sites")
place = models.OneToOneField(
Place,
on_delete=models.CASCADE,
verbose_name="related place",
)
La convención es no capitalizar la primera letra del verbose_name. Django capitalizará automáticamente la primera letra donde sea necesario.
Claramente, el poder de las bases de datos relacionales reside en la relación entre tablas. Django ofrece formas para definir los tres tipos más comunes de relaciones de base de datos: muchos a uno, muchos a muchos y uno a uno.
Para definir una relación muchos a uno, utilice django.db.models.ForeignKey. Lo utiliza exactamente como cualquier otro tipo de campo Field: incluyéndolo como un atributo de clase de tu modelo.
ForeignKey requiere un argumento posicional: la clase a la que el modelo está relacionado.
Por ejemplo, si un modelo Car tiene una Manufacturer – es decir, una Manufacturer hace múltiples coches pero cada Car solo tiene una Manufacturer – utilice las siguientes definiciones:
from django.db import models
class Manufacturer(models.Model):
# ...
pass
class Car(models.Model):
manufacturer = models.ForeignKey(Manufacturer, on_delete=models.CASCADE)
# ...
También puedes crear relaciones recursivas (un objeto con una relación muchos a uno consigo mismo) y relaciones con modelos no aún definidos para detalles.
Se sugiere, pero no se requiere, que el nombre de un campo ForeignKey (manufacturer en el ejemplo anterior) sea el nombre del modelo, en minúsculas. Puedes llamar al campo lo que quieras. Por ejemplo:
class Car(models.Model):
company_that_makes_it = models.ForeignKey(
Manufacturer,
on_delete=models.CASCADE,
)
# ...
Ver también
Los campos ForeignKey aceptan una serie de argumentos adicionales que se explican en la referencia de campos del modelo. Estas opciones ayudan a definir cómo debe funcionar la relación; todas son opcionales.
Para detalles sobre el acceso a objetos relacionados hacia atrás, vea el ejemplo de relaciones hacia atrás.
Para ver código de ejemplo, vea el documento Ejemplo de modelo de relación muchos a uno.
Para definir una relación muchos-a-muchos, utiliza la clase ~django.db.models.ManyToManyField. La utilizas de la misma manera que cualquier otro tipo de campo: incluyéndolo como un atributo de clase de tu modelo.
La clase ~django.db.models.ManyToManyField requiere un argumento posicional: la clase a la que el modelo está relacionado.
Por ejemplo, si una Pizza tiene múltiples objetos Topping – es decir, un objeto Topping puede estar en múltiples pizzas y cada Pizza tiene múltiples topping – aquí tienes cómo representarlo:
from django.db import models
class Topping(models.Model):
# ...
pass
class Pizza(models.Model):
# ...
toppings = models.ManyToManyField(Topping)
Al igual que con ~django.db.models.ForeignKey, también puedes crear relaciones recursivas <recursive-relationships> (un objeto con una relación muchos-a-muchos consigo mismo) y relaciones a modelos no definidos aún <lazy-relationships>.
Se sugiere, pero no es obligatorio, que el nombre de un ~django.db.models.ManyToManyField (toppings en el ejemplo anterior) sea plural y describa el conjunto de objetos de modelo relacionados.
No importa qué modelo tiene la clase ~django.db.models.ManyToManyField, pero solo debes ponerla en uno de los modelos – no en ambos.
En general, las instancias de ~django.db.models.ManyToManyField deben ir en el objeto que se va a editar en un formulario. En el ejemplo anterior, toppings está en Pizza (en lugar de Topping tener una pizzas ~django.db.models.ManyToManyField) porque es más natural pensar en una pizza con topping que en una topping que esté en múltiples pizzas. De la forma en que se ha configurado arriba, el formulario Pizza permitiría a los usuarios seleccionar las topping.
Ver también
Consulta el ejemplo de modelo de relación muchos-a-muchos <topics/db/examples/many_to_many> para ver un ejemplo completo.
Los campos ~django.db.models.ManyToManyField también aceptan una serie de argumentos adicionales que se explican en la referencia del campo de modelo <manytomany-arguments>. Estas opciones ayudan a definir cómo debe funcionar la relación; todas son opcionales.
When estás tratando solo con relaciones muchos-a-muchos como mezclar y combinar pizzas y toppings, una relación estándar ManyToManyField es todo lo que necesitas. Sin embargo, a veces puede ser necesario asociar datos con la relación entre dos modelos.
Por ejemplo, considera el caso de una aplicación que rastree los grupos musicales a los cuales pertenecen los músicos. Hay una relación muchos-a-muchos entre una persona y los grupos de los cuales es miembro, por lo que podrías usar una ManyToManyField para representar esta relación. Sin embargo, hay mucho detalle sobre la membresía que podrías querer recopilar, como la fecha en la cual el personaje se unió al grupo.
Para estas situaciones, Django te permite especificar el modelo que se utilizará para gobernar la relación muchos-a-muchos. Puedes poner campos adicionales en el modelo intermedio. El modelo intermedio está asociado con la ManyToManyField utilizando el argumento through para apuntar al modelo que actuará como intermediario. Para nuestro ejemplo de músico, el código sería algo así:
from django.db import models
class Person(models.Model):
name = models.CharField(max_length=128)
def __str__(self):
return self.name
class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(Person, through="Membership")
def __str__(self):
return self.name
class Membership(models.Model):
person = models.ForeignKey(Person, on_delete=models.CASCADE)
group = models.ForeignKey(Group, on_delete=models.CASCADE)
date_joined = models.DateField()
invite_reason = models.CharField(max_length=64)
class Meta:
constraints = [
models.UniqueConstraint(
fields=["person", "group"], name="unique_person_group"
)
]
Cuando configuras el modelo intermedio, especificas explícitamente claves foráneas a los modelos que están involucrados en la relación muchos-a-muchos. Esta declaración explícita define cómo se relacionan los dos modelos.
Si no quieres múltiples asociaciones entre las mismas instancias, agrega una UniqueConstraint incluyendo los campos from y to. Las tablas de muchos-a-muchos generadas automáticamente por Django incluyen tal restricción.
Hay algunas restricciones en el modelo intermedio:
Tu modelo intermedio debe contener una - y solo una - clave foránea al modelo fuente (este sería Group en nuestro ejemplo), o debes especificar explícitamente las claves foráneas que Django debería utilizar para la relación utilizando ManyToManyField.through_fields. Si tienes más de una clave foránea y no se ha especificado through_fields, se levantará un error de validación. Una restricción similar aplica a la clave foránea al modelo objetivo (este sería Person en nuestro ejemplo).
Para un modelo que tiene una relación muchos-a-muchos consigo mismo a través de un modelo intermedio, se permiten dos claves foráneas al mismo modelo, pero se tratarán como las dos (diferentes) partes de la relación muchos-a-muchos. Si no se ha especificado through_fields, la primera clave foránea se tomará para representar el lado fuente del ManyToManyField, mientras que la segunda se tomará para representar el lado objetivo. Si hay más de dos claves foráneas, debes especificar through_fields para indicar explícitamente cuáles claves foráneas utilizar, de lo contrario se levantará un error de validación.
Ahora que has configurado tu ManyToManyField para usar tu modelo intermedio (Membership, en este caso), estás listo para empezar a crear algunas relaciones muchos-a-muchos. Lo haces creando instancias del modelo intermedio:
>>> ringo = Person.objects.create(name="Ringo Starr")
>>> paul = Person.objects.create(name="Paul McCartney")
>>> beatles = Group.objects.create(name="The Beatles")
>>> m1 = Membership(
... person=ringo,
... group=beatles,
... date_joined=date(1962, 8, 16),
... invite_reason="Needed a new drummer.",
... )
>>> m1.save()
>>> beatles.members.all()
<QuerySet [<Person: Ringo Starr>]>
>>> ringo.group_set.all()
<QuerySet [<Group: The Beatles>]>
>>> m2 = Membership.objects.create(
... person=paul,
... group=beatles,
... date_joined=date(1960, 8, 1),
... invite_reason="Wanted to form a band.",
... )
>>> beatles.members.all()
<QuerySet [<Person: Ringo Starr>, <Person: Paul McCartney>]>
También puedes utilizar add(), create() o set() para crear relaciones, siempre y cuando especifiques through_defaults para cualquier campo requerido:
>>> beatles.members.add(john, through_defaults={"date_joined": date(1960, 8, 1)})
>>> beatles.members.create(
... name="George Harrison", through_defaults={"date_joined": date(1960, 8, 1)}
... )
>>> beatles.members.set(
... [john, paul, ringo, george], through_defaults={"date_joined": date(1960, 8, 1)}
... )
You may prefer to create instances of the intermediate model directly.
Si la tabla de tránsito definida por el modelo intermedio no impone unicidad en la pareja (model1, model2), permitiendo múltiples valores, la llamada a remove() eliminará todas las instancias del modelo intermedio:
>>> Membership.objects.create(
... person=ringo,
... group=beatles,
... date_joined=date(1968, 9, 4),
... invite_reason="You've been gone for a month and we miss you.",
... )
>>> beatles.members.all()
<QuerySet [<Person: Ringo Starr>, <Person: Paul McCartney>, <Person: Ringo Starr>]>
>>> # This deletes both of the intermediate model instances for Ringo Starr
>>> beatles.members.remove(ringo)
>>> beatles.members.all()
<QuerySet [<Person: Paul McCartney>]>
El método clear() se puede utilizar para eliminar todas las relaciones muchos-a-muchos para una instancia:
>>> # Beatles have broken up
>>> beatles.members.clear()
>>> # Note that this deletes the intermediate model instances
>>> Membership.objects.all()
<QuerySet []>
Una vez que hayas establecido las relaciones muchos-a-muchos, puedes emitir consultas. Al igual que con las relaciones muchos-a-muchos normales, puedes consultar utilizando los atributos del modelo relacionado muchos-a-muchos:
# Find all the groups with a member whose name starts with 'Paul'
>>> Group.objects.filter(members__name__startswith="Paul")
<QuerySet [<Group: The Beatles>]>
Como estás usando un modelo intermedio, también puedes consultar en sus atributos:
# Find all the members of the Beatles that joined after 1 Jan 1961
>>> Person.objects.filter(
... group__name="The Beatles", membership__date_joined__gt=date(1961, 1, 1)
... )
<QuerySet [<Person: Ringo Starr]>
Si necesitas acceder a la información de una membresía, puedes hacerlo directamente consultando el modelo Membership:
>>> ringos_membership = Membership.objects.get(group=beatles, person=ringo)
>>> ringos_membership.date_joined
datetime.date(1962, 8, 16)
>>> ringos_membership.invite_reason
'Needed a new drummer.'
Otra forma de acceder a la misma información es consultando la relación inversa muchos-a-muchos <m2m-reverse-relationships> desde un objeto Person:
>>> ringos_membership = ringo.membership_set.get(group=beatles)
>>> ringos_membership.date_joined
datetime.date(1962, 8, 16)
>>> ringos_membership.invite_reason
'Needed a new drummer.'
Para definir una relación uno-a-uno, utiliza OneToOneField. Lo utilizas exactamente como cualquier otro tipo de campo: incluyéndolo como atributo de clase de tu modelo.
Esto es más útil en la clave primaria de un objeto cuando ese objeto «extiende» a otro objeto de alguna manera.
OneToOneField requiere una argumento posicional: la clase a la que el modelo está relacionado.
For example, if you were building a database of «places», you would build pretty standard stuff such as address, phone number, etc. in the database. Then, if you wanted to build a database de restaurantes sobre la base de lugares, en lugar de repetirte y replicar esos campos en el modelo Restaurant, podrías hacer que Restaurant tenga un OneToOneField con Place (porque un restaurante «es un» lugar; en realidad, para manejar esto típicamente se utiliza la herencia de modelos, que implica una relación uno-a-uno implícita).
As with ForeignKey, a relación recursiva puede ser definida y referencias a modelos aún no definidos pueden hacerse.
Ver también
Consulte el ejemplo de modelo de relación uno-a-uno completo en la sección Relaciones uno-a-uno.
Los campos de tipo OneToOneField también aceptan un argumento opcional parent_link.
Las clases de campo OneToOneField utilizadas para convertirse automáticamente en la clave primaria de un modelo. Esto ya no es cierto (aunque puedes pasar manualmente el argumento primary_key si lo deseas). Por tanto, ahora es posible tener múltiples campos del tipo OneToOneField en un solo modelo.
Está perfectamente bien relacionar un modelo con uno de otra aplicación. Para hacer esto, importa el modelo relacionado en la parte superior del archivo donde se define tu modelo. Luego, refiérete a la clase del otro modelo donde sea necesario. Por ejemplo:
from django.db import models
from geography.models import ZipCode
class Restaurant(models.Model):
# ...
zip_code = models.ForeignKey(
ZipCode,
on_delete=models.SET_NULL,
blank=True,
null=True,
)
Alternativamente, puedes utilizar una referencia relajada al modelo relacionado, especificada como una cadena en el formato "app_label.ModelName". Esto no requiere que el modelo relacionado esté importado. Por ejemplo:
from django.db import models
class Restaurant(models.Model):
# ...
zip_code = models.ForeignKey(
"geography.ZipCode",
on_delete=models.SET_NULL,
blank=True,
null=True,
)
Consulte relaciones relajadas para obtener más detalles.
Django establece algunas restricciones en los nombres de campos del modelo:
Un nombre de campo no puede ser una palabra reservada de Python, ya que eso daría como resultado un error de sintaxis de Python. Por ejemplo:
class Example(models.Model):
pass = models.IntegerField() # 'pass' is a reserved word!
Un nombre de campo no puede contener más de un guión bajo seguido en una fila, debido a la forma en que funciona la sintaxis de búsqueda de consultas de Django. Por ejemplo:
class Example(models.Model):
foo__bar = models.IntegerField() # 'foo__bar' has two underscores!
Un nombre de campo no puede terminar con un guión bajo, por razones similares.
Un nombre de campo no puede ser check, ya que esto sobrescribiría el método Model.check() del marco de trabajo de verificación.
Estas limitaciones se pueden superar, aunque, porque tu nombre de campo no necesita coincidir necesariamente con el nombre de columna de la base de datos. Consulta la opción db_column.
Las palabras reservadas SQL, como join, where o select, son permitidas como nombres de campos del modelo, ya que Django escape todos los nombres de tabla y columnas de la base de datos en cada consulta SQL subyacente. Utiliza el sintaxis de citación de su motor de base de datos particular.
Si uno de los campos del modelo existente no puede usarse para ajustarse a tus necesidades, o si deseas aprovechar algunos tipos menos comunes de columnas de la base de datos, puedes crear tu propio tipo de campo. La cobertura completa de la creación de tus propios campos se proporciona en Cómo crear campos de modelo personalizados.
Meta¶Proporciona metadatos de tu modelo utilizando una clase interna class Meta, como se muestra a continuación:
from django.db import models
class Ox(models.Model):
horn_length = models.IntegerField()
class Meta:
ordering = ["horn_length"]
verbose_name_plural = "oxen"
La información de metadatos del modelo es «cualquier cosa que no sea un campo», como opciones de ordenación (ordering), nombre de la tabla de base de datos (db_table) o nombres singulares y plurales legibles por humanos (verbose_name y verbose_name_plural). Ninguna es obligatoria, y agregar class Meta a un modelo es completamente opcional.
Una lista completa de todas las opciones posibles de Meta se puede encontrar en la referencia de la opción del modelo <ref:models/options>.
El atributo más importante de un modelo es el Manager. Es la interfaz a través de la cual se proporcionan operaciones de consulta de base de datos a los modelos Django y se utiliza para recuperar las instancias desde la base de datos. Si no se define un nombre personalizado Manager, el nombre predeterminado es objects. Los administradores solo están accesibles a través de clases de modelos, no a través de instancias de modelo.
Define métodos personalizados en un modelo para agregar funcionalidad de nivel de fila personalizada a tus objetos. Mientras que los métodos de la clase Manager están destinados a hacer cosas «de nivel de tabla», los métodos del modelo deben actuar sobre una instancia de modelo particular.
Esta es una técnica valiosa para mantener la lógica de negocio en un solo lugar – el modelo.
Ejemplo: este modelo tiene unos pocos métodos personalizados:
from django.db import models
class Person(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
birth_date = models.DateField()
def baby_boomer_status(self):
"Returns the person's baby-boomer status."
import datetime
if self.birth_date < datetime.date(1945, 8, 1):
return "Pre-boomer"
elif self.birth_date < datetime.date(1965, 1, 1):
return "Baby boomer"
else:
return "Post-boomer"
@property
def full_name(self):
"Returns the person's full name."
return f"{self.first_name} {self.last_name}"
El último método en este ejemplo es un property.
La referencia al instante de modelo <doc>`</ref/models/instances>` tiene una lista completa de los métodos que se le dan automáticamente a cada modelo: métodos del modelo. Puedes sobrescribir la mayoría de estos – véase sobreescribiendo métodos predefinidos del modelo, más abajo – pero hay un par que casi siempre querrás definir:
__str__()Un método «mágico» de Python que devuelve una representación en cadena de cualquier objeto. Esto es lo que Python y Django usarán cada vez que necesiten coercer e mostrar un instante de modelo como una cadena simple. De manera notable, esto sucede cuando se muestra un objeto en una consola interactiva o en la interfaz administrativa.
Siempre querrás definir este método; el valor por defecto no es muy útil en absoluto.
get_absolute_url()Esto le dice a Django cómo calcular la URL para un objeto. Django utiliza esto en su interfaz administrativa, y cada vez que necesita determinar una URL para un objeto.
Cualquier objeto que tenga una URL que lo identifique de manera única debería definir este método.
Hay otro conjunto de métodos del modelo que encapsulan un montón de comportamiento de base de datos que querrás personalizar. En particular, a menudo querrás cambiar la forma en que funcionan save() y delete().
Puedes sobrescribir estos métodos (y cualquier otro método de modelo) para alterar el comportamiento.
Un uso clásico del caso de uso es si deseas que algo suceda siempre que se guarde un objeto. Por ejemplo (consulte la documentación de los parámetros que acepta save() para más detalles):
from django.db import models
class Blog(models.Model):
name = models.CharField(max_length=100)
tagline = models.TextField()
def save(self, **kwargs):
do_something()
super().save(**kwargs) # Call the "real" save() method.
do_something_else()
También puedes evitar guardar:
from django.db import models
class Blog(models.Model):
name = models.CharField(max_length=100)
tagline = models.TextField()
def save(self, **kwargs):
if self.name == "Yoko Ono's blog":
return # Yoko shall never have her own blog!
else:
super().save(**kwargs) # Call the "real" save() method.
Es importante recordar llamar al método del superclase – es ese super().save(**kwargs) negocio – para asegurarte de que el objeto todavía se guarde en la base de datos. Si olvidas llamar al método del superclase, el comportamiento predeterminado no sucederá y la base de datos no se tocará.
Es importante también pasar los argumentos que se pueden pasar a la función del modelo – es lo que hace **kwargs. Django, de vez en cuando, extenderá las capacidades de las funciones de modelos incorporadas, agregando nuevos argumentos de palabra clave. Si utilizas **kwargs en tus definiciones de métodos, estás garantizando que tu código automáticamente apoyará esos argumentos cuando se agreguen.
Si deseas actualizar un valor de campo en el método save(), también podrías querer tener este campo agregado a la argumento update_fields de palabra clave. Esto asegurará que el campo se guarde cuando update_fields esté especificado. Por ejemplo:
from django.db import models
from django.utils.text import slugify
class Blog(models.Model):
name = models.CharField(max_length=100)
slug = models.TextField()
def save(self, **kwargs):
self.slug = slugify(self.name)
if (
update_fields := kwargs.get("update_fields")
) is not None and "name" in update_fields:
kwargs["update_fields"] = {"slug"}.union(update_fields)
super().save(**kwargs)
Consulte Especificar los campos a guardar para obtener más detalles.
Los métodos sobrescritos del modelo no se llaman en operaciones de lote
Ten en cuenta que el método delete() de un objeto no es necesariamente llamado cuando se eliminan objetos en lote utilizando una QuerySet o como resultado de una eliminación cascada. Para asegurarte de que la lógica de eliminación personalizada se ejecuta, puedes utilizar los señales pre_delete y/o post_delete.
Desafortunadamente, no hay un trabajo alrededor cuando creando o actualizando objetos en lote, ya que ninguno de los métodos save(), pre_save y post_save se llaman.
Otra patrón común es escribir sentencias SQL personalizadas en métodos de modelos y métodos a nivel de módulo. Para obtener más detalles sobre el uso de SQL crudo, consulte la documentación sobre uso de SQL crudo.
La herencia de modelos en Django funciona casi identicamente a la forma en que funciona la herencia normal de clases en Python, pero los fundamentos al principio de la página todavía deben seguirse. Eso significa que la clase base debe heredar de django.db.models.Model.
La única decisión que debes tomar es si quieres que los modelos padre sean modelos en su propio derecho (con sus propias tablas de bases de datos), o si los padres son solo contenedores de información común que solo serán visibles a través de los modelos hijos.
Hay tres estilos de herencia posibles en Django.
A menudo, solo quieres utilizar la clase padre para almacenar información que no deseas tener que escribir para cada modelo hijo. Esta clase nunca se usará en isolation, por lo que clases base abstractas son lo que estás buscando.
Si estás heredando de un modelo existente (quizás algo de otra aplicación completamente) y quieres que cada modelo tenga su propia tabla de bases de datos, herencia multi-tabla es la forma de ir.
Finalmente, si solo quieres modificar el comportamiento a nivel de Python de un modelo, sin cambiar los campos del modelo en absoluto, puedes utilizar modelos proxy.
Las traducciones son:
Un ejemplo:
from django.db import models
class CommonInfo(models.Model):
name = models.CharField(max_length=100)
age = models.PositiveIntegerField()
class Meta:
abstract = True
class Student(CommonInfo):
home_group = models.CharField(max_length=5)
El modelo Student tendrá tres campos: name, age y home_group. El modelo CommonInfo no puede utilizarse como un modelo Django normal, ya que es una clase base abstracta. No genera ninguna tabla de base de datos ni tiene un administrador, y no se puede instanciar o guardar directamente.
Los campos heredados de las clases base abstractas pueden sobrescribirse con otro campo o valor, o eliminarse con None.
Para muchos usos, este tipo de herencia de modelos será exactamente lo que deseas. Proporciona una forma de factorizar la información común a nivel de Python, mientras se crea solo una tabla de base de datos por modelo hijo en el nivel de la base de datos.
Meta¶Cuando se crea una clase base abstracta, Django hace que cualquier clase Meta interna que declaraste en la clase base esté disponible como un atributo. Si una clase hija no declara su propia clase Meta, heredará la de la clase padre. Si la clase hija quiere extender la clase Meta del padre, puede sobrescribirla. Por ejemplo:
from django.db import models
class CommonInfo(models.Model):
# ...
class Meta:
abstract = True
ordering = ["name"]
class Student(CommonInfo):
# ...
class Meta(CommonInfo.Meta):
db_table = "student_info"
Django hace una ajuste en la clase Meta de una clase base abstracta: antes de instalar el atributo Meta, establece abstract=False. Esto significa que los hijos de las clases base abstractas no se convierten automáticamente en clases abstractas ellas mismas. Para hacer una clase base abstracta que hereda de otra clase base abstracta, debes establecer explícitamente abstract=True en la hija.
Algunos atributos no tienen sentido incluirlos en la clase Meta de una clase base abstracta. Por ejemplo, incluir db_table significaría que todas las clases hijas (las que no especifican su propia clase Meta) utilizarían la misma tabla de base de datos, lo cual es casi con certeza no lo que deseas.
Debido a la forma en que funciona la herencia de Python, si una clase hija hereda de múltiples clases base abstractas, solo las opciones Meta de la primera clase listada se heredarán por defecto. Para heredar opciones Meta de múltiples clases base abstractas, debes declarar explícitamente la herencia de Meta. Por ejemplo:
from django.db import models
class CommonInfo(models.Model):
name = models.CharField(max_length=100)
age = models.PositiveIntegerField()
class Meta:
abstract = True
ordering = ["name"]
class Unmanaged(models.Model):
class Meta:
abstract = True
managed = False
class Student(CommonInfo, Unmanaged):
home_group = models.CharField(max_length=5)
class Meta(CommonInfo.Meta, Unmanaged.Meta):
pass
El segundo tipo de herencia de modelos admitido por Django es cuando cada modelo en la jerarquía es un modelo por sí solo. Cada modelo corresponde a su propia tabla de base de datos y puede ser consultado y creado individualmente. La relación de herencia introduce vínculos entre el modelo hijo y cada uno de sus padres (a través de un OneToOneField creado automáticamente). Por ejemplo:
from django.db import models
class Place(models.Model):
name = models.CharField(max_length=50)
address = models.CharField(max_length=80)
class Restaurant(Place):
serves_hot_dogs = models.BooleanField(default=False)
serves_pizza = models.BooleanField(default=False)
Todas las field de Place también estarán disponibles en Restaurant, aunque los datos residirán en una tabla de base de datos diferente. Por lo tanto, ambas son posibles:
>>> Place.objects.filter(name="Bob's Cafe")
>>> Restaurant.objects.filter(name="Bob's Cafe")
Si tienes un objeto Place que también es un Restaurant, puedes obtener el objeto Restaurant desde el objeto Place utilizando la versión en minúsculas del nombre del modelo:
>>> p = Place.objects.get(id=12)
# If p is a Restaurant object, this will give the child class:
>>> p.restaurant
<Restaurant: ...>
Sin embargo, si en el ejemplo anterior p no fuera un objeto Restaurant (había sido creado directamente como un objeto Place o era el padre de alguna otra clase), referirse a p.restaurant levantaría una excepción Restaurant.DoesNotExist.
La relación automáticamente creada por OneToOneField entre Restaurant y Place se ve así:
place_ptr = models.OneToOneField(
Place,
on_delete=models.CASCADE,
parent_link=True,
primary_key=True,
)
Puedes sobreescribir ese campo declarando tu propio OneToOneField con parent_link=True en Restaurant.
En la situación de herencia multi-tabla, no tiene sentido que una clase hija herede de la clase Meta de su padre. Todas las opciones de Meta ya han sido aplicadas a la clase padre y aplicarlas nuevamente normalmente solo conduciría a comportamientos contradictorios (esto es en contraste con el caso de la clase base abstracta, donde la clase base no existe por derecho propio).
Un modelo hijo no tiene acceso a la clase Meta de su padre. Sin embargo, hay unos pocos casos limitados en los que el hijo hereda comportamiento del padre: si el hijo no especifica un atributo ordering o un atributo get_latest_by, lo heredará de su padre.
Si el padre tiene un ordenamiento y no deseas que el hijo tenga ningún ordenamiento natural, puedes deshabilitarlo explícitamente:
class ChildModel(ParentModel):
# ...
class Meta:
# Remove parent's ordering effect
ordering = []
Porque la herencia en varias tablas utiliza un campo de relación implícito OneToOneField para vincular al hijo con el padre, es posible moverse desde el padre hacia el hijo, como se muestra en el ejemplo anterior. Sin embargo, esto utiliza el nombre que es el valor por defecto de la propiedad related_name para las relaciones ForeignKey y ManyToManyField. Si estás poniendo esos tipos de relaciones en una subclase del modelo padre, debes especificar la propiedad related_name en cada campo así. Si lo olvidas, Django lanzará un error de validación.
Por ejemplo, utilizando el clase Place anterior, crea otra subclase con una relación ManyToManyField:
class Supplier(Place):
customers = models.ManyToManyField(Place)
Esto da como resultado el error:
Reverse query name for 'Supplier.customers' clashes with reverse query
name for 'Supplier.place_ptr'.
HINT: Add or change a related_name argument to the definition for
'Supplier.customers' or 'Supplier.place_ptr'.
Añadiendo la propiedad related_name al campo customers de la siguiente manera se resolvería el error: models.ManyToManyField(Place, related_name='provider').
Como se mencionó anteriormente, Django creará automáticamente un campo de relación OneToOneField que vincule tu clase hijo con cualquier modelo padre no abstracto. Si quieres controlar el nombre del atributo que vincula hacia el padre, puedes crear tu propio campo de relación OneToOneField y establecer la propiedad parent_link=True para indicar que tu campo es el enlace hacia la clase padre.
Cuando se utiliza la herencia en varias tablas <multi-table-inheritance>, una nueva tabla de base de datos se crea para cada subclase de un modelo. Esto suele ser el comportamiento deseado, ya que la subclase necesita un lugar para almacenar cualquier campo de datos adicional que no esté presente en la clase base. A veces, sin embargo, solo quieres cambiar el comportamiento de Python de un modelo – tal vez para cambiar el administrador por defecto o agregar una nueva función.
Esto es lo que la herencia de modelos proxy está hecha para: crear un proxy del modelo original. Puedes crear, eliminar y actualizar instancias del modelo proxy y todo el dato se guardará como si estuvieras utilizando el modelo original (no proxificado). La diferencia es que puedes cambiar cosas como el ordenamiento por defecto del modelo o el administrador por defecto en el proxy, sin tener que alterar el original.
Los modelos proxy se declaran como los modelos normales. Dices a Django que es un modelo proxy estableciendo la propiedad proxy de la clase Meta a True.
Para agregar un método al modelo Person puedes hacerlo de la siguiente manera:
from django.db import models
class Person(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
class MyPerson(Person):
class Meta:
proxy = True
def do_something(self):
# ...
pass
La clase MyPerson opera en la misma tabla de la base de datos que su clase padre Person. En particular, cualquier nueva instancia de Person también será accesible a través de MyPerson, y viceversa:
>>> p = Person.objects.create(first_name="foobar")
>>> MyPerson.objects.get(first_name="foobar")
<MyPerson: foobar>
También podrías utilizar un modelo proxy para definir un ordenamiento diferente por defecto en un modelo. Es posible que no siempre quieras ordenar el modelo Person, pero regularmente ordenar por el atributo last_name cuando utilices el proxy:
class OrderedPerson(Person):
class Meta:
ordering = ["last_name"]
proxy = True
Ahora las consultas normales de Person serán desordenadas y las consultas de OrderedPerson estarán ordenadas por last_name.
Los modelos proxy heredan los atributos Meta de la misma manera que los modelos regulares.
QuerySets todavía devuelven el modelo solicitado¶No existe forma de hacer que Django devuelva, digamos, un objeto MyPerson cada vez que se consulta por objetos Person. Una colección de consultas para objetos Person devolverá esos tipos de objetos. El punto principal de los objetos proxy es que el código que depende del original Person utilizará esos y tu propio código puede usar las extensiones que incluyiste (que ningún otro código está confiando en de todas maneras). No es una forma de reemplazar el modelo Person (o cualquier otro) por algo de tu propia creación en todos los lugares.
Un modelo proxy debe heredar exactamente de una clase de modelo no abstracta. No puedes heredar de múltiples modelos no abstractos ya que el modelo proxy no proporciona ninguna conexión entre las filas en las diferentes tablas de la base de datos. Un modelo proxy puede heredar de cualquier número de clases de modelo abstracto siempre y cuando éstas no definan ningún campo del modelo. Un modelo proxy también puede heredar de cualquier número de modelos proxy que compartan una clase base no abstracta común.
Si no especificas ningún administrador de modelos en un modelo proxy, hereda los administradores de sus padres de modelo. Si defines un administrador en el modelo proxy, se convertirá en el predeterminado, aunque cualquier administrador definido en las clases padre seguirá estando disponible.
Continuando con nuestro ejemplo anterior, podrías cambiar el administrador por defecto utilizado al consultar el modelo Person de la siguiente manera:
from django.db import models
class NewManager(models.Manager):
# ...
pass
class MyPerson(Person):
objects = NewManager()
class Meta:
proxy = True
Si deseas agregar un nuevo administrador al Proxy, sin reemplazar el existente por defecto, puedes utilizar las técnicas descritas en la documentación sobre administradores personalizados: crea una clase base que contenga los nuevos administradores y hereda esa después de la clase principal:
# Create an abstract class for the new manager.
class ExtraManagers(models.Model):
secondary = NewManager()
class Meta:
abstract = True
class MyPerson(Person, ExtraManagers):
class Meta:
proxy = True
Probablemente no necesites hacer esto muy a menudo, pero cuando lo hagas, es posible.
La herencia de modelos proxy puede parecer similar a crear un modelo no gestionado utilizando el atributo managed en la clase Meta del modelo.
Con una configuración cuidadosa de Meta.db_table podrías crear un modelo no gestionado que se asemeje a un modelo existente y agregue métodos Python a él. Sin embargo, eso sería muy repetitivo y frágil ya que necesitarías mantener ambas copias sincronizadas si haces algún cambio.
Por otro lado, los modelos proxy están diseñados para comportarse exactamente como el modelo al que se están proxyizando. Siempre están en sincronía con el modelo padre ya que heredan directamente sus campos y administradores.
Las reglas generales son:
Si estás reflejando un modelo o tabla de base de datos existente y no deseas todas las columnas originales de la tabla de base de datos, utiliza Meta.managed=False. Esa opción es normalmente útil para modelar vistas de base de datos y tablas que no están bajo el control de Django.
Si deseas cambiar el comportamiento de Python solo de un modelo, pero mantener todos los mismos campos como en la original, utiliza Meta.proxy=True. Esto configura las cosas para que el modelo proxy sea una copia exacta de la estructura de almacenamiento del modelo original cuando se guardan los datos.
Justo como con la herencia en Python, es posible que un modelo Django herede de múltiples modelos padre. Ten en cuenta que las reglas normales de resolución de nombres de Python se aplican. La primera clase base en la que aparece un nombre particular (por ejemplo, Meta) será la utilizada; por ejemplo, esto significa que si varios padres contienen una clase Meta, solo la primera se utilizará y las demás serán ignoradas.
Normalmente no necesitarás heredar de múltiples padres. El principal caso de uso donde esto es útil es para clases «mix-in»: agregar un campo o método extra particular a cada clase que herede la mix-in. Trata de mantener tus jerarquías de herencia lo más simples y directas posible para que no tengas que luchar para determinar dónde está una pieza de información particular.
Ten en cuenta que heredar de múltiples modelos con un campo primario id común provocará un error. Para utilizar la herencia múltiple correctamente, puedes usar un campo AutoField explícito en las clases base:
class Article(models.Model):
article_id = models.AutoField(primary_key=True)
...
class Book(models.Model):
book_id = models.AutoField(primary_key=True)
...
class BookReview(Book, Article):
pass
O utiliza un ancestro común para mantener el AutoField. Esto requiere usar un campo OneToOneField explícito desde cada modelo padre al ancestro común para evitar un conflicto entre los campos que se generan automáticamente e heredan por el hijo:
class Piece(models.Model):
pass
class Article(Piece):
article_piece = models.OneToOneField(
Piece, on_delete=models.CASCADE, parent_link=True
)
...
class Book(Piece):
book_piece = models.OneToOneField(Piece, on_delete=models.CASCADE, parent_link=True)
...
class BookReview(Book, Article):
pass
En la herencia normal de clases en Python, es permisible que una clase hija sobreescriba cualquier atributo de la clase padre. En Django, esto no suele estar permitido para los campos de modelo. Si una clase base no abstracta tiene un campo llamado author, no puedes crear otro campo de modelo o definir un atributo llamado author en ninguna clase que herede esa clase base.
Esta restricción no se aplica a los campos de modelo heredados de una clase base abstracta. Dichos campos pueden sobreescribirse con otro campo o valor, o eliminarse estableciendo field_name = None.
Advertencia
Los administradores de modelos se heredan de las clases base abstractas. Sobrescribir un campo heredado que es referenciado por un administrador Manager puede causar problemas sutiles. Consulta administradores personalizados y herencia de modelos.
Nota
Algunos campos definen atributos adicionales en el modelo, por ejemplo, un ForeignKey define un atributo adicional con _id agregado al nombre del campo, así como related_name y related_query_name en el modelo extranjero.
Estos atributos adicionales no pueden ser sobrescritos a menos que el campo que los define sea cambiado o eliminado de modo que ya no defina el atributo adicional.
Sobreescribir campos en un modelo padre conlleva dificultades en áreas como la inicialización de nuevas instancias (especificando qué campo se está inicializando en Model.__init__) y serialización. Estas son características que la herencia de clases Python normales no tienen que tratar de la misma manera, por lo que la diferencia entre la herencia de modelos Django y la herencia de clases Python no es arbitraria.
Esta restricción solo se aplica a atributos que son instancias de Field. Los atributos normales de Python pueden ser sobrescritos si así lo deseas. También solo se aplica al nombre del atributo como lo ve Python: si estás especificando manualmente el nombre de la columna de la base de datos, puedes tener el mismo nombre de columna apareciendo en un modelo hijo y un modelo antecesor para la herencia multi-tabla (son columnas en dos tablas de bases de datos diferentes).
Django lanzará una FieldError si sobreescribes cualquier campo del modelo en algún modelo antecesor.
Ten en cuenta que debido a la forma en que se resuelven los campos durante la definición de la clase, los campos de modelos heredados de múltiples modelos abstractos padres se resuelven en un orden estricto de profundidad. Esto contrasta con el MRO estándar de Python, que se resuelve de forma ancha en casos de herencia en forma de diamante. Esta diferencia solo afecta a jerarquías de modelos complejas, lo cual (como se indica arriba) debes tratar de evitar.
El comando manage.py startapp crea una estructura de aplicación que incluye un archivo models.py. Si tienes muchos modelos, organizarlos en archivos separados puede ser útil.
Para hacerlo, crea un paquete models. Elimina el archivo models.py y crea un directorio myapp/models/ con un archivo __init__.py y los archivos para almacenar tus modelos. Debes importar los modelos en el archivo __init__.py.
Por ejemplo, si tenías organic.py y synthetic.py en el directorio models:
myapp/models/__init__.py¶from .organic import Person
from .synthetic import Robot
Importando explícitamente cada modelo en lugar de utilizar from .models import * tiene las ventajas de no ensuciar el espacio de nombres, hacer que el código sea más legible y mantener útiles las herramientas de análisis del código.
Ver también
Cubre todas las APIs relacionadas con los modelos, incluyendo campos de modelo, objetos relacionados y QuerySet.
may 31, 2026