onetoonefield foreign django django-models django-users django-profiles

Django: Al extender el usuario, mejor usar OneToOneField(usuario) o ForeignKey(usuario, único=verdadero)?



django foreign key (3)

Estoy encontrando información conflictiva sobre si usar OneToOneField (Usuario) o ForeignKey (Usuario, único = Verdadero) al crear un modelo de Perfil de Usuario extendiendo el modelo de Usuario de Django.

¿Es mejor usar esto ?:

class UserProfile(models.Model): user = models.ForeignKey(User, unique=True)

¿o esto?:

class UserProfile(models.Model): user = models.OneToOneField(User)

El documento de Django especifica OneToOneField, mientras que el ejemplo de Django Book usa ForeignKey.

James Bennett también tiene dos publicaciones en el blog que proporcionan ejemplos contradictorios:

En la publicación anterior, Bennett proporciona algunas razones por las que cambió a usar ForeignKey en lugar de OneToOneField, pero no lo entiendo, especialmente cuando veo otras publicaciones que recomiendan lo contrario.

Tengo curiosidad por saber tu preferencia y por qué. ¿Ó acaso importa?


Además de las páginas de administración, otra razón para la solución ForeignKey es que le permite usar el administrador de base de datos predeterminado correcto cuando se accede a los objetos con una relación inversa. Considere el ejemplo de este fragmento de administrador de subclases . Digamos que la definición de la clase Post del ejemplo se ve así:

class Post(ParentModel): title = models.CharField(max_length=50) onetoone = models.ForeignKey(SomeModel, unique=True) children = ChildManager() objects = models.Manager()

Al llamar a somemodel_instance.post_set.all()[0] , obtiene los objetos de las subclases deseadas de la clase Post como se indica definiendo el primer administrador (predeterminado) como ChildManager . Por otro lado, con OneToOneField , al llamar a somemodel_instance.post obtiene la instancia de la clase Post . Siempre puede llamar a somemodel_instance.post.subclass_object y obtener el mismo resultado, pero el administrador predeterminado podría hacer cualquier otro tipo de trucos y las soluciones FK ocultan muy bien.

Si posee y puede modificar el código del administrador personalizado, puede usar el atributo use_for_related_fields lugar de usar FK en lugar del campo 1to1 legítimo, pero incluso eso puede fallar debido a algunas molestias no conocidas por parte de los administradores automáticos. Por lo que recuerdo, fallará en el ejemplo anterior.


La única razón real que se da en el artículo es que se puede configurar para que la página de administración del User muestre los campos en User y User de User . Esto se puede replicar con OneToOneField con un poco de OneToOneField , así que a menos que seas adicto a mostrarlo en la página de administración sin trabajo a costa de un poco de claridad ("Podemos crear múltiples perfiles por usuario ?! Oh no , espera, es único. ") Utilizaría OneToOneField .


Otra razón para no utilizar generalmente OneToOneField relacionado con las relaciones inversas: cuando utiliza relaciones inversas definidas a través de OneToOneField , obtiene una instancia de modelo, a diferencia de la relación inversa de Manager for ForeignKey y como consecuencia siempre hay un hit DB. Esto es costoso si usted hace algunas cosas genéricas en las relaciones inversas (a través de _meta.get_all_related_objects() ) y no sabe y le importa si las usará todas o no.