through one objects many foreign example python django many-to-many foreign-key-relationship one-to-one

python - objects - ¿Cuál es la diferencia entre un campo OneToOne, ManyToMany y ForeignKey en Django?



model many to many relationship django (1)

Estoy teniendo un poco de dificultad para entender las relaciones en los modelos de Django.

¿Alguien podría explicar cuál es la diferencia entre OneToOne, ManyToMany y ForeignKey?


Bueno, hay esencialmente dos preguntas aquí:

  1. ¿Cuál es la diferencia (en general) entre uno a uno, muchos a muchos y relaciones clave externas?
  2. ¿Cuáles son sus diferencias específicas a Django.

Ambas preguntas se contestan con bastante facilidad a través de una simple búsqueda en Google, pero como no puedo encontrar un duplicado exacto de esta pregunta en SO, seguiré adelante y responderé.

Tenga en cuenta que en Django, las relaciones solo deben definirse en un lado de la relación.

Clave externa

Una relación de clave externa se conoce generalmente como una relación de muchos a uno. Tenga en cuenta que lo contrario de esta relación es de uno a muchos (a la que Django proporciona herramientas para acceder). Como su nombre lo indica, muchos objetos pueden estar relacionados con uno.

Person <--> Birthplace

En este ejemplo, una persona puede tener solo un lugar de nacimiento, pero un lugar de nacimiento puede estar relacionado con muchas personas. Veamos este ejemplo en Django. Digamos que estos son nuestros modelos:

class Birthplace(models.Model): city = models.CharField(max_length=75) state = models.CharField(max_length=25) def __unicode__(self): return "".join(self.city, ", ", self.state) class Person(models.Model): name = models.CharField(max_length=50) birthplace = models.ForeignKey(Birthplace) def __unicode__(self): return self.name

Puede ver que no hay relaciones definidas dentro del modelo de Birthplace , y una relación ForeignKey está definida dentro del modelo de Person . Digamos que creamos los siguientes modelos (obviamente no en la sintaxis de Python):

  • Lugar de nacimiento: Dallas, Texas
  • Lugar de nacimiento: Nueva York, Nueva York.
  • Persona: John Smith, Lugar de nacimiento: (Dallas, Texas)
  • Persona: Maria Lee, Lugar de nacimiento: (Dallas, Texas)
  • Persona: Daniel Lee, Lugar de nacimiento: (Nueva York, Nueva York)

Ahora podemos ver cómo Django nos permite usar estas relaciones (tenga en cuenta que el ./manage.py shell es su amigo):

>> from somewhere.models import Birthplace, Person >> Person.objects.all() [<Person: John Smith>, <Person: Maria Lee>, <Person: Daniel Lee>] >> Birthplace.objects.all() [<Birthplace: Dallas, Texas>, <Birthplace: New York City, New York>]

Puedes ver nuestros modelos creados. Ahora vamos a ver el lugar de nacimiento de alguien:

>> person = Person.object.get(name="John Smith") >> person.birthplace <Birthplace: Dallas, Texas> >> person.birthplace.city Dallas

Digamos que quieres ver a todas las personas con un lugar de nacimiento determinado. Como dije anteriormente, Django te permite acceder a relaciones inversas. De forma predeterminada, Django crea un administrador ( RelatedManager ) en su modelo para manejar esto, denominado <model>_set , donde <model> es el nombre de su modelo en minúscula.

>> place = Birthplace.objects.get(city="Dallas") >> place.person_set.all() [<Person: John Smith>, <Person: Maria Lee>]

Tenga en cuenta que podemos cambiar el nombre de este administrador estableciendo el argumento de palabra clave related_name en nuestra relación de modelo. Por lo tanto, cambiaríamos el campo de birthplace en el modelo de Person a:

birthplace = models.ForeignKey(Birthplace, related_name="people")

Ahora, podemos acceder a esa relación inversa con un nombre bonito:

>> place.people.all() [<Person: John Smith>, <Person: Maria Lee>]

Doce y cincuenta y nueve de la noche

Una relación de uno a uno es bastante similar a una relación de muchos a uno, excepto que restringe dos objetos a tener una relación única. Un ejemplo de esto sería un usuario y un perfil (que almacena información sobre el usuario). No hay dos usuarios que compartan el mismo perfil. Veamos esto en Django. No me molestaré en definir el modelo de usuario, como lo define Django para nosotros. Sin embargo, tenga en cuenta que Django sugiere usar django.contrib.auth.get_user_model() para importar al usuario, así que eso es lo que haremos. El modelo de perfil se puede definir de la siguiente manera:

class Profile(models.Model): user = models.OneToOneField(settings.AUTH_USER_MODEL) # Note that Django suggests getting the User from the settings for relationship definitions fruit = models.CharField(max_length=50, help_text="Favorite Fruit") facebook = models.CharField(max_length=100, help_text="Facebook Username") def __unicode__(self): return "".join(self.fruit, " ", self.facebook)

Todo lo que necesitamos es un usuario con un perfil para probar esto en el shell:

  • Usuario: johndt6
  • Perfil: usuario: johndt6, "Kiwi", "blah_blah"

Ahora puede acceder fácilmente al perfil del usuario desde el modelo de usuario:

>> user = User.objects.all()[0] >> user.username johndt6 >> user.profile <Profile: Kiwi blah_blah> >> user.profile.fruit Kiwi >> profile = Profile.objects.get(user=user) >> profile.user <User: johndt6>

Por supuesto, puede personalizar el nombre de la relación inversa usando el argumento related_name como se related_name anteriormente.

Muchos a muchos

Las relaciones de muchos a muchos pueden ser un poco difíciles. Permítanme comenzar diciendo que los campos de muchos a muchos son confusos, y deben evitarse cuando sea posible. Dado esto, hay muchas situaciones en las que una relación de muchos a muchos tiene sentido.

Una relación de muchos a muchos entre dos modelos define que cero, uno o más objetos del primer modelo pueden estar relacionados con cero, uno o más objetos del segundo modelo. Como ejemplo, imaginemos una empresa que define su flujo de trabajo a través de proyectos. Un proyecto puede estar relacionado con ningún pedido, solo un pedido o muchos pedidos. Una orden puede estar relacionada con ningún proyecto, un proyecto o muchos. Definamos nuestros modelos como tal:

class Order(models.Model): product = models.CharField(max_length=150) # Note that in reality, this would probably be better served by a Product model customer = models.CharField(max_length=150) # The same may be said for customers def __unicode__(self): return "".join(self.product, " for ", self.customer) class Project(models.Model): orders = models.ManyToManyField(Order) def __unicode__(self): return "".join("Project ", str(self.id))

Tenga en cuenta que Django creará un RelatedManager para que el campo de orders acceda a la relación de muchos a muchos.

Vamos a crear los siguientes objetos (en mi sintaxis inconsistente!):

  • Orden: "Nave espacial", "NASA"
  • Orden: "Submarino", "Marina de los Estados Unidos"
  • Orden: "Coche de carreras", "NASCAR"
  • Proyecto: pedidos: []
  • Proyecto: órdenes: [(Orden: "Nave espacial", "NASA")]
  • Proyecto: órdenes: [(Orden: "Nave espacial", "NASA"), (Orden: "Coche de carreras", "NASCAR")]

Podemos acceder a estas relaciones de la siguiente manera:

>> Project.objects.all() [<Project: Project 0>, <Project: Project 1>, <Project: Project 2>] >> for proj in Project.objects.all(): .. print(proj) .. proj.orders.all() # Note that we must access the `orders` .. # field through its manager .. print("") Project 0 [] Project 1 [<Order: Spaceship for NASA>] Project 2 [<Order: Spaceship for NASA>, <Order: Race car for NASCAR>]

Tenga en cuenta que la orden de la NASA está relacionada con 2 proyectos, y la orden de la Marina de los EE. UU. Está relacionada con ninguno. También tenga en cuenta que un proyecto no tiene órdenes, y uno tiene múltiples.

También podemos acceder a la relación a la inversa de la misma manera que antes:

>> order = Order.objects.filter(customer="NASA")[0] >> order.project_set.all() [<Project: Project 0>, <Project: Project 2>]

Recursos

databaseprimer.com/pages/table-relationships proporcionadas por @MarcB

Página de Wikipedia en Cardinalidad.

Django Docs:

models.ForeignKey

models.OneToOneField

models.ManyToManyField

Relaciones Uno a Uno

Relaciones de muchos a muchos