2011-08-03 17 views
100

Estoy definiendo mis modelos Django en este momento y me di cuenta de que no había un OneToManyField en los tipos de campo modelo. Estoy seguro de que hay una manera de hacerlo, así que no estoy seguro de lo que me estoy perdiendo. Esencialmente tener algo como esto:Cómo expresar una relación Uno a Muchos en Django

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

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

En este caso, cada Dude puede tener múltiples PhoneNumber s, pero la relación debería ser unidireccional, en la que no necesito saber desde el cual PhoneNumberDude posee, per se, como que podría tener muchos objetos diferentes que poseen PhoneNumber casos, como por ejemplo un Business:

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

¿Qué iba a reemplazar OneToManyField (que no existe) con en el modelo para representar a este k ind de la relación? Vengo de Hibernate/JPA, donde se declara una relación uno-a-muchos era tan fácil como:

@OneToMany 
private List<PhoneNumber> phoneNumbers; 

¿Cómo puedo expresar esto en Django?

Respuesta

67

Para manejar las relaciones One-To-Many en Django necesita usar ForeignKey.

La documentación sobre ForeignKey es muy amplio y debe responder a todas las preguntas que tenga:

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

La estructura actual en su ejemplo permite a cada Amigo para tener un número, y cada número de pertenecer a múltiples Dudes (lo mismo con los negocios).

Si desea la relación inversa, deberá agregar dos campos ForeignKey a su modelo PhoneNumber, uno a Dude y uno a Business. Esto permitiría que cada número pertenezca a un solo Amigo o un Negocio, y que los Tíos y las Empresas puedan poseer varios Números. 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) 
+1

¿Podría darme un ejemplo dado el problema anterior? Probablemente me lo estoy perdiendo por completo, pero he estado leyendo la documentación de Django desde hace un tiempo y aún no estoy claro cómo crear este tipo de relación. –

+3

podría querer hacer que las dos ForeignKeys no sean necesarias (en blanco = True, null = True) o agregar algún tipo de validación personalizada para asegurarse de que haya al menos una u otra. ¿Qué pasa con el caso de una empresa que tiene un número genérico? o un tipo desempleado? –

+1

@j_syk buen punto acerca de la validación personalizada. pero parece algo estrafalario incluir tanto una clave foránea como una clave externa para las empresas, y luego hacer una validación personalizada (externa a la definición del modelo). parece que tiene que haber una manera más limpia, pero tampoco puedo resolverlo. – andy

29

En Django, una relación de uno a muchos se llama ForeignKey. Sólo funciona en una dirección, sin embargo, por lo que en lugar de tener un atributo de la clase numberDude necesitará

class Dude(models.Model): 
    ... 

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

Muchos modelos pueden tener un ForeignKey a otro modelo, por lo que sería válida para tener un segundo atributo de tal manera que PhoneNumber

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

puede acceder a los PhoneNumber s para un objeto dDude con d.phonenumber_set.objects.all(), y luego hacer lo mismo para un objeto Business.

+1

Estaba bajo la suposición de que 'ForeignKey' significaba" uno a uno ". Usando su ejemplo anterior, debería tener un 'Amigo' que tenga muchos' Números de teléfono' ¿verdad? –

+4

Edité mi respuesta para reflejar esto. Sí. 'ForeignKey' es solo uno a uno si especifica' ForeignKey (Dude, unique = True) ', de modo que con el código anterior obtendrá' Dude' con múltiples 'PhoneNumber's. – stillLearning

+1

@rolling stone- gracias, estaba agregando eso después de darme cuenta de mi error como usted comentó. Unique = True no funciona exactamente igual que OneToOneField; quise explicar que ForeignKey solo usa una relación de uno a uno si especifica Unique = True. – stillLearning

7

Puede usar cualquier clave externa en muchos lados de la relación OneToMany (es decir, relación ManyToOne) o use ManyToMany (en cualquier lado) con una restricción única.

Cuestiones relacionadas