À partir des documents Django.Contrib.Auth :
Extension de l'utilisateur par défaut de Django Si vous êtes entièrement satisfait du modèle utilisateur de Django et que vous souhaitez simplement ajouter des informations de profil supplémentaires, vous pouvez simplement sous-classe
Django.contrib.auth.models.AbstractUser
et ajouter 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 se voit dans l’administrateur presque comme le User
standard de Django. Cependant, la différence la plus importante dans l’administration réside dans le fait que le champ password (re) set n’est pas présent, mais qu’un CharField normal s’affiche. Dois-je vraiment écraser les éléments dans admin-config pour que cela fonctionne? Si tel est le cas, comment puis-je le faire de manière quelque peu DRY (c'est-à-dire sans copier d'éléments de la source Django ... eww ...)?
Après avoir fouillé dans le code source de Django pendant un moment, j'ai trouvé une âme qui fonctionne. Je ne suis pas totalement satisfait de cette solution, mais elle semble fonctionner. N'hésitez pas à suggérer de meilleures solutions!
Django utilise UserAdmin
pour rendre à l'administrateur Nice le modèle User
. En utilisant simplement ceci dans notre fichier admin.py
-, nous pouvons obtenir la même apparence pour notre modèle.
from Django.contrib.auth.admin import UserAdmin
admin.site.register(MyUser, UserAdmin)
Cependant, cela seul n'est probablement pas une bonne solution, puisque Django Admin n'affichera aucun de vos champs spéciaux. Il y a deux raisons à cela:
UserAdmin
utilise UserChangeForm
comme formulaire à utiliser pour modifier l'objet, 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éé un formulaire de modification spécial qui surcharge la classe interne Meta de sorte que le formulaire de modification utilise le modèle correct. J'ai également dû surcharger UserAdmin
pour ajouter mes champs spéciaux à la zone de champs, ce qui est la partie de cette solution qui me déplaît un peu, car elle a l'air un peu moche. N'hésitez pas à suggérer des améliorations!
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 réponse de nico a été extrêmement utile, mais j'ai trouvé que Django faisait toujours référence au modèle User 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 supplémentaires à 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)
Une solution plus 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 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'ajouter un champ personnalisé au formulaire de création. Peut-être que ça a changé depuis la 1.6.2? Quoi qu'il en soit, j'ai trouvé que l'ajout du champ aux deux champs et add_fieldsets ont fait l'affaire.
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 ( A pris d'ici ):
from __future__ import unicode_literals
from Django.contrib import admin
from Django.contrib.auth.admin import UserAdmin
from Django.contrib.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)