Utiliser Django Auth UserAdmin pour un modèle d’utilisateur personnalisé

A partir des documents Django.Consortingb.Auth :

Extension de l’utilisateur par défaut de Django Si vous êtes entièrement satisfait du modèle d’utilisateur de Django et que vous souhaitez simplement append des informations de profil supplémentaires, vous pouvez simplement sous- django.consortingb.auth.models.AbstractUser et append vos champs de profil personnalisés. Cette classe fournit l’implémentation complète de l’utilisateur par défaut en tant que modèle abstrait.

Dit et fait. J’ai créé un nouveau modèle comme ci-dessous:

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

Cela apparaît dans admin presque comme l’ User standard de Django. Cependant, la différence la plus importante dans admin réside dans le fait que le champ password- (re) set n’est pas présent, mais un CharField normal est affiché à la place. Dois-je vraiment remplacer les éléments de la configuration admin pour que cela fonctionne? Si oui, comment puis-je le faire de manière un peu sèche (c.-à-d. Sans copier les éléments de la source Django … eww …)?

Après avoir fouillé le code source de Django pendant un moment, j’ai trouvé une solution de travail. Je ne suis pas totalement satisfait de cette solution, mais cela semble fonctionner. N’hésitez pas à proposer de meilleures solutions!


Django utilise UserAdmin pour rendre le bel aspect admin pour User modèle User . En utilisant simplement ceci dans notre admin.py admin.py, nous pouvons obtenir le même aspect pour notre modèle.

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

Cependant, cette solution n’est probablement pas une bonne solution, car l’administrateur Django n’affichera aucun de vos champs spéciaux. Il y a deux raisons à cela:

  • UserAdmin utilise UserChangeForm comme formulaire à utiliser lors de la modification de l’object, qui à son tour utilise User comme modèle.
  • UserAdmin définit une propriété formsets, utilisée ultérieurement par UserChangeForm , qui n’inclut pas vos champs spéciaux.

J’ai donc créé une forme de modification spéciale qui surcharge la classe interne Meta afin que le formulaire de modification utilise le modèle correct. J’ai également dû surcharger UserAdmin pour append mes champs spéciaux dans le jeu de champs, ce qui est la partie de cette solution que je déteste un peu, car elle est un peu moche. N’hésitez pas à suggérer des améliorations!

 from django.consortingb.auth.admin import UserAdmin from django.consortingb.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 réponse de nico a été extrêmement utile, mais j’ai trouvé que Django faisait toujours référence au modèle de l’utilisateur lors de la création d’un nouvel utilisateur.

Ticket # 19353 fait référence à ce problème.

Afin de résoudre ce problème, j’ai dû faire quelques ajouts à admin.py

admin.py:

 from django.consortingb import admin from django.consortingb.auth.admin import UserAdmin from django.consortingb.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) 

Une solution plus simple, admin.py:

 from django.consortingb.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 référencera correctement le modèle MyUser pour la création et la modification. J’utilise Django 1.6.2.

La réponse de cesc ne fonctionnait pas pour moi lorsque j’ai tenté d’append un champ personnalisé au formulaire de création. Peut-être que cela a changé depuis 1.6.2? De toute façon, j’ai trouvé l’ajout du champ aux deux sets de champs et à add_fieldsets.

 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) 

Une autre solution similaire (prise d’ici ):

 from __future__ import unicode_literals from django.consortingb import admin from django.consortingb.auth.admin import UserAdmin from django.consortingb.auth.models import AbstractUser from django.utils.translation import ugettext_lazy as _ from .models import User class UserAdminWithExtraFields(UserAdmin): def __init__(self, *args, **kwargs): super(UserAdminWithExtraFields, self).__init__(*args, **kwargs) abstract_fields = [field.name for field in AbstractUser._meta.fields] user_fields = [field.name for field in self.model._meta.fields] self.fieldsets += ( (_('Extra fields'), { 'fields': [ f for f in user_fields if ( f not in abstract_fields and f != self.model._meta.pk.name ) ], }), ) admin.site.register(User, UserAdminWithExtraFields)