2010-07-11 21 views
29

Estoy encontrando información contradictoria 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.Django: Al extender el usuario, mejor utilizar OneToOneField (usuario) o ForeignKey (usuario, único = verdadero)?

¿Es mejor utilizar esto ?:

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

o esto ?:

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

El Django Doc especifica OneToOneField, mientras que el Django Book example utiliza ForeignKey.

James Bennett también tiene dos puestos de blog que proporcionan ejemplos en conflicto, así:

En el primer puesto, Bennett proporciona algunas razones por las que pasado a utilizar ForeignKey vez de OneToOneField, pero no lo entiendo, especialmente cuando veo otras publicaciones que recomiendan lo contrario.

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

+0

No veo nada en el primer artículo de Bennett con respecto a los perfiles de usuario. –

+0

@Ignacio - Disculpa, agregué un enlace al artículo equivocado. Debería haber sido en su publicación sobre "Extender el modelo de usuario". He corregido el enlace. Gracias por señalar esto. –

+0

Para mí, http://stackoverflow.com/questions/5870537/whats-the-difference-between-django-onetoonefield-and-foreignkey es más claro de entender –

Respuesta

17

La única razón real dada en el artículo es que se puede configurar para que la página de administración para User muestre los campos en User y UserProfile. Esto se puede replicar con OneToOneField con un poco de esfuerzo, 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.

7

Además de las páginas de administración, otro motivo 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 subclasses manager snippet. Digamos que la definición Post clase del ejemplo es el siguiente:

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

    children = ChildManager() 
    objects = models.Manager() 

Llamando somemodel_instance.post_set.all()[0], se obtiene las subclases de objetos deseados de la clase Post como se indica mediante la definición del primer gestor (por defecto) como un ChildManager. Por otro lado, con OneToOneField, al llamar al somemodel_instance.post, obtiene la instancia de clase Post. Siempre puede llamar al 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 los ocultan muy bien.

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

5

Otra razón por lo general a no utilizar los OneToOneField relacionados con las relaciones inversa: cuando se utiliza las relaciones inversas define a través OneToOneField se obtiene una instancia de modelo, al contrario de Manager para ForeignKey relación inversa y como consecuencia siempre hay un DB golpeó.Esto es costoso si haces algunas cosas genéricas en las relaciones inversas (a través de _meta.get_all_related_objects()) y no sabes y te importa si las usarás todas o no.

Cuestiones relacionadas