¿Cómo expresar una relación uno a muchos en Django?

Resuelto Naftuli Kay asked hace 13 años • 11 respuestas

Estoy definiendo mis modelos de Django en este momento y me di cuenta de que no había ningún OneToManyFieldtipo de campo en el modelo. Estoy seguro de que hay una manera de hacer esto, así que no estoy seguro de lo que me estoy perdiendo. Básicamente tengo algo como esto:

class Dude(models.Model):
    # 1 dude can have 0+ phone numbers
    numbers = models.OneToManyField('PhoneNumber')

class PhoneNumber(models.Model):
    number = models.CharField()

En este caso, cada uno Dudepuede tener múltiples PhoneNumbers, pero la relación debe ser unidireccional, en el sentido de que no necesito saber quién PhoneNumberlo Dudeposee, per se, ya que podría tener muchos objetos diferentes que posean PhoneNumberinstancias, como un Businessfor ejemplo:

class Business(models.Model):
    numbers = models.OneToManyField('PhoneNumber')

¿Con qué reemplazaría OneToManyField(que no existe) en el modelo para representar este tipo de relación? Vengo de Hibernate/JPA donde declarar una relación de uno a muchos era tan fácil como:

@OneToMany
private List<PhoneNumber> phoneNumbers;

¿Cómo puedo expresar esto en Django?

Naftuli Kay avatar Aug 03 '11 22:08 Naftuli Kay
Aceptado

Para manejar relaciones uno a muchos en Django necesitas usar ForeignKey.

La documentación ForeignKeyes muy completa y debería responder a todas las preguntas que tenga:

https://docs.djangoproject.com/en/3.2/ref/models/fields/#foreignkey

La estructura actual en su ejemplo permite que cada uno Dudetenga un número y que cada número pertenezca a varios Dudes (lo mismo ocurre con Business).


Si desea la relación inversa, deberá agregar dos ForeignKeycampos a su PhoneNumbermodelo, uno para Dudey otro para Business. Esto permitiría que cada número pertenezca a uno Dudeo uno Business, y que Dudesy Businesses pueda poseer múltiples PhoneNumbers. Creo que esto podría ser lo que buscas:

class Business(models.Model):
    ...

class Dude(models.Model):
    ...

class PhoneNumber(models.Model):
    dude = models.ForeignKey(Dude)
    business = models.ForeignKey(Business)
rolling stone avatar Aug 03 '2011 15:08 rolling stone

En Django, una relación de uno a muchos se llama ForeignKey. Sin embargo, sólo funciona en una dirección, por lo que en lugar de tener un numberatributo de clase Dudenecesitarás

class Dude(models.Model):
    ...

class PhoneNumber(models.Model):
    dude = models.ForeignKey(Dude)

Muchos modelos pueden tener un ForeignKeya otro modelo, por lo que sería válido tener un segundo atributo de PhoneNumbertal que

class Business(models.Model):
    ...
class Dude(models.Model):
    ...
class PhoneNumber(models.Model):
    dude = models.ForeignKey(Dude)
    business = models.ForeignKey(Business)

Puede acceder al PhoneNumbers de un Dudeobjeto dcon d.phonenumber_set.objects.all()y luego hacer lo mismo con un Businessobjeto.

stillLearning avatar Aug 03 '2011 15:08 stillLearning

Para ser más claro, no hay OneToMany en Django, solo ManyToOne, que es Foreignkey descrito anteriormente. Puede describir la relación OneToMany usando Foreignkey, pero eso es muy inexpresivo.

Un buen artículo al respecto: https://amir.rachum.com/blog/2013/06/15/a-case-for-a-onetomany-relationship-in-django/

validname avatar Jun 05 '2018 10:06 validname