with extender contrib auth django django-models django-authentication django-users django-contrib

extender - login with django user



Django: ¿Por qué crear OneToOne para UserProfile en lugar de crear una subclase de auth.User? (3)

¿Es más eficiente y efectivo heredar el modelo de Usuario? No veo por qué, pero me gustaría leer tus argumentos. IMNSHO, la herencia modelo siempre ha sido un dolor.

Sin embargo, es posible que esto no responda a su pregunta, pero estoy bastante satisfecho con la solución propuesta por Will Hardy en este fragmento . Al aprovechar las señales, crea automáticamente un nuevo perfil de usuario para cada nuevo usuario.

Es poco probable que el enlace desaparezca, pero aquí está mi versión ligeramente diferente de su código:

from django.contrib.auth.models import User from django.db import models from django.db.models.signals import post_save from django.utils.translation import ugettext_lazy as _ class AuthUserProfileModelBase(models.base.ModelBase): # _prepare is not part of the public API and may change def _prepare(self): super(AuthUserProfileModelBase, self)._prepare() def on_save(sender, instance, created, **kwargs): if created: self.objects.create(user=instance) # Automatically link profile when a new user is created post_save.connect(on_save, sender=User, weak=False) # Every profile model must inherit this class class AuthUserProfileModel(models.Model): class Meta: abstract = True __metaclass__ = AuthUserProfileModelBase user = models.OneToOneField(User, db_column=''auth_user_id'', primary_key=True, parent_link=True) # The actual profile model class Profile(AuthUserProfileModel): class Meta: app_label = ''some_app_label'' db_table = ''auth_user_profile'' managed = True language = models.CharField(_(''language''), max_length=5, default=''en'')

Por supuesto, cualquier crédito va para Will Hardy.

Nota: Si tiene la tentación de ''responder'' esta pregunta diciéndome que no le gusta django.contrib.auth, continúe. Eso no será útil. Soy muy consciente del alcance y la fuerza de las opiniones sobre este asunto.

Ahora, la pregunta:

La convención es crear un modelo, UserProfile, con OneToOne para el usuario.

En todos los sentidos que se me ocurre, un enfoque más eficiente y eficaz es clasificar al usuario en una clase que se pretende usar para cada ser humano en el sistema: una clase llamada, por ejemplo, Persona (Usuario).

No he visto una explicación coherente de por qué el primero es convencional y el último es considerado como un hack. Hace un tiempo, cambié al enfoque OneToOne para obtener la capacidad de usar get_profile () y lo he lamentado desde entonces. Estoy pensando en volver a pasar a menos que se me haga comprender la ventaja de este enfoque.


Te das cuenta, ¿no es así, que la subclasificación del modelo se implementa mediante una relación OneToOne bajo el capó? De hecho, en lo que respecta a la eficiencia, no veo ninguna diferencia entre estos dos métodos.

La creación de subclase de modelos de concreto existentes es, en mi opinión, un truco desagradable que debería evitarse si es posible. Implica ocultar una relación de base de datos para que no esté claro cuándo se realiza el acceso a db adicional. Es mucho más claro mostrar explícitamente las relaciones y acceder a ellas explícitamente cuando sea necesario.

Ahora, una tercera alternativa que me gusta es crear un modelo de usuario completamente nuevo, junto con un backend de autenticación personalizado que devuelve instancias del nuevo modelo en lugar del modelo predeterminado. Crear un backend solo implica definir un par de métodos simples, por lo que es muy fácil de hacer.


Realmente nunca ha habido una buena explicación, al menos de fuentes "oficiales" sobre por qué, en la práctica, la subclasificación de usuarios es menos útil que tener un perfil de usuario.

Sin embargo, tengo un par de razones que surgieron después de decidirme a mí mismo que el usuario de subclases era "el camino a seguir".

  • Necesita un back-end de autenticación personalizado. Esto no es un gran problema, pero cuanto menos código necesite escribir, mejor.
  • Otras aplicaciones pueden suponer que su Usuario es un django.contrib.auth.models.User . En general, esto estará bien, a menos que ese código esté buscando objetos de Usuario. Debido a que somos una subclase, cualquier código que use nuestros objetos Usuario debería estar bien.
  • Un usuario solo puede ''ser'' una subclase a la vez. Por ejemplo, si tiene subclases de Usuario de Estudiante y Profesor, entonces, en un momento dado, su Usuario solo podrá ser un Profesor o un Estudiante. Con UserProfiles, podría haber un perfil de Profesor y de Estudiante adjunto al mismo usuario al mismo tiempo.
  • A continuación, la conversión de una subclase a otra es difícil: especialmente si ya tiene una instancia de una subclase.

Por lo tanto, puede decir: "mi proyecto solo tendrá una única subclase de usuario". Es lo que pensaba. Ahora tenemos tres, más usuarios regulares, y posiblemente un cuarto. Los requisitos cambian , tener que cambiar montones de código para tratar eso no es muy divertido.

nota: Recientemente ha habido mucha discusión sobre django-developers sobre una mejor solución a los problemas relacionados con el modelo de usuario contrib.auth.