django django-models django-admin django-authentication django-custom-user

Usar Django auth UserAdmin para un modelo de usuario personalizado



extend user model django (4)

De los documentos de Django.Contrib.Auth :

Ampliación del usuario predeterminado de Django Si está completamente satisfecho con el modelo de usuario de Django y solo desea agregar información de perfil adicional, puede simplemente subclase django.contrib.auth.models.AbstractUser y agregar sus campos de perfil personalizados. Esta clase proporciona la implementación completa del usuario predeterminado como modelo abstracto.

Dicho y hecho. Creé un nuevo modelo como a continuación:

class MyUser(AbstractUser): some_extra_data = models.CharField(max_length=100, blank=True)

Esto aparece en el administrador casi como el User estándar de Django. Sin embargo, la diferencia más importante en admin es que el campo de contraseña (re) no está presente, pero en su lugar se muestra un CharField normal. ¿Realmente tengo que anular cosas en la configuración de administrador para que esto funcione? Si es así, ¿cómo puedo hacerlo de una manera SECA (es decir, sin copiar cosas de la fuente de Django ... eww ...)?


Después de investigar el código fuente de Django por un tiempo, encontré una alma de trabajo. No estoy totalmente satisfecho con esta solución, pero parece funcionar. ¡Siéntase libre de sugerir mejores soluciones!

Django usa UserAdmin para UserAdmin el buen aspecto de administrador para el modelo de User . Con solo usar esto en nuestro admin.py admin.py, podemos obtener el mismo aspecto para nuestro modelo.

from django.contrib.auth.admin import UserAdmin admin.site.register(MyUser, UserAdmin)

Sin embargo, esto solo probablemente no sea una buena solución, ya que Django Admin no mostrará ninguno de sus campos especiales. Hay dos razones para esto:

  • UserAdmin usa UserChangeForm como el formulario que se utilizará al modificar el objeto, que a su vez utiliza al User como su modelo.
  • UserAdmin define un conjunto de formsets -propiedad, más tarde utilizado por UserChangeForm , que no incluye sus campos especiales.

Entonces, creé una forma de cambio especial que sobrecarga la clase interna Meta de modo que la forma de cambio use el modelo correcto. También tuve que sobrecargar UserAdmin para agregar mis campos especiales al fieldset, que es la parte de esta solución que me disgusta un poco, ya que se ve un poco feo. ¡Siéntase libre de sugerir mejoras!

from django.contrib.auth.admin import UserAdmin from django.contrib.auth.forms import UserChangeForm class MyUserChangeForm(UserChangeForm): class Meta(UserChangeForm.Meta): model = MyUser class MyUserAdmin(UserAdmin): form = MyUserChangeForm fieldsets = UserAdmin.fieldsets + ( (None, {''fields'': (''some_extra_data'',)}), ) admin.site.register(MyUser, MyUserAdmin)


La respuesta de cesc no me funcionaba cuando intenté agregar un campo personalizado al formulario de creación. Tal vez ha cambiado desde 1.6.2? De cualquier manera, encontré agregar el campo a ambos conjuntos de campos y add_fieldsets hizo el truco.

ADDITIONAL_USER_FIELDS = ( (None, {''fields'': (''some_additional_field'',)}), ) class MyUserAdmin(UserAdmin): model = MyUser add_fieldsets = UserAdmin.add_fieldsets + ADDITIONAL_USER_FIELDS fieldsets = UserAdmin.fieldsets + ADDITIONAL_USER_FIELDS admin.site.register(MyUser, MyUserAdmin)


La respuesta de nico ha sido extremadamente útil, pero encontré que Django todavía hace referencia al modelo de usuario cuando crea un nuevo usuario.

El boleto #19353 referencia a este problema.

Para arreglarlo, tuve que hacer algunas adiciones más a admin.py

admin.py:

from django.contrib import admin from django.contrib.auth.admin import UserAdmin from django.contrib.auth.forms import UserChangeForm, UserCreationForm from main.models import MyUser from django import forms class MyUserChangeForm(UserChangeForm): class Meta(UserChangeForm.Meta): model = MyUser class MyUserCreationForm(UserCreationForm): class Meta(UserCreationForm.Meta): model = MyUser def clean_username(self): username = self.cleaned_data[''username''] try: MyUser.objects.get(username=username) except MyUser.DoesNotExist: return username raise forms.ValidationError(self.error_messages[''duplicate_username'']) class MyUserAdmin(UserAdmin): form = MyUserChangeForm add_form = MyUserCreationForm fieldsets = UserAdmin.fieldsets + ( (None, {''fields'': (''extra_field1'', ''extra_field2'',)}), ) admin.site.register(MyUser, MyUserAdmin)


Una solución más simple, admin.py:

from django.contrib.auth.admin import UserAdmin from main.models import MyUser class MyUserAdmin(UserAdmin): model = MyUser fieldsets = UserAdmin.fieldsets + ( (None, {''fields'': (''some_extra_data'',)}), ) admin.site.register(MyUser, MyUserAdmin)

Django referenciará correctamente el modelo MyUser para creación y modificación. Estoy usando Django 1.6.2.