使用Django auth UserAdmin作为自定义用户模型

nip*_*p3o 73 django django-models django-admin django-authentication django-custom-user

来自Django.Contrib.Auth文档:

扩展Django的默认用户 如果您对Django的用户模型完全满意并且只想添加一些其他配置文件信息,您可以简单地子类化django.contrib.auth.models.AbstractUser并添加自定义配置文件字段.此类提供默认用户的完整实现作为抽象模型.

说完了.我创建了一个如下所示的新模型:

class MyUser(AbstractUser):
  some_extra_data = models.CharField(max_length=100, blank=True)
Run Code Online (Sandbox Code Playgroud)

这显示在管理员中几乎像Django的标准User.但是,admin中最重要的区别是密码 - (重新)设置字段不存在,而是显示正常的CharField.我是否真的必须覆盖admin-config中的内容才能使其正常工作?如果是这样,我怎么能以某种干燥的方式做到这一点(即没有从Django源中复制东西......等等......)?

nip*_*p3o 118

在挖掘了Django源代码一段时间后,我发现了一个有效的灵魂.我对这个解决方案并不完全满意,但似乎有效.随意提出更好的解决方案!


Django用于UserAdmin渲染User模型的漂亮管理员外观.通过在我们的admin.py-file中使用它,我们可以获得与模型相同的外观.

from django.contrib.auth.admin import UserAdmin
admin.site.register(MyUser, UserAdmin)
Run Code Online (Sandbox Code Playgroud)

但是,仅凭这一点可能不是一个好的解决方案,因为Django Admin不会显示任何特殊字段.有两个原因:

  • UserAdminUserChangeForm用作修改对象时使用的形式,而对象又User用作模型.
  • UserAdmin定义formsets-property,稍后使用UserChangeForm,不包括您的特殊字段.

因此,我创建了一个特殊的更改形式,它重载了Meta内部类,以便更改表单使用正确的模型.我还必须重载UserAdmin以将我的特殊字段添加到fieldset,这是我不喜欢的解决方案的一部分,因为它看起来有点难看.随意提出改进建议!

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)
Run Code Online (Sandbox Code Playgroud)

  • 另请注意,您需要根据@ kdh454的答案覆盖用户创建表单. (6认同)

小智 54

nico的回答非常有用,但我发现Django在创建新用户时仍然引用了User模型.

机票#19353引用了这个问题.

为了解决它,我不得不再做一些补充 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)
Run Code Online (Sandbox Code Playgroud)

  • 请注意,从1.6开始,对`forms.ValidationError`的调用有第二个参数:`code ='duplicate_username':https://github.com/django/django/blob/1.6/django/contrib/auth/forms .py#L101-L104另外,我在1.6.5上尝试了这个,由于某种原因,我根本不需要覆盖`UserChangeForm`,并且更改表单在我的自定义字段中工作正常.我无法解释原因.它似乎不应该有效,因为`UserChangeForm`类具有`model = User` present:https://github.com/django/django/blob/1.6.5/django/contrib/auth/forms. PY#L138 (3认同)
  • FYI票[#19353](https://code.djangoproject.com/ticket/19353)现已修复,这实际上意味着您的解决方案可能是多余的.如果我们只使用@ nip3o的解决方案,我们应该很好. (2认同)

小智 44

一个更简单的解决方案,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)
Run Code Online (Sandbox Code Playgroud)

Django将正确引用MyUser模型进行创建和修改.我正在使用Django 1.6.2.

  • 相反让`None`,你可以输入一个字符串,它将被用作管理表单中的部分的标题 (2认同)

aid*_*ni8 6

当我尝试向创建表单添加自定义字段时,cesc的答案对我不起作用。也许自1.6.2起已更改?无论哪种方式,我都发现将字段添加到两个fieldset和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)
Run Code Online (Sandbox Code Playgroud)