首页 文章

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

提问于
浏览
65

来自Django.Contrib.Auth docs

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

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

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

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

5 回答

  • 34

    一个更简单的解决方案, 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将正确引用MyUser模型进行创建和修改 . 我正在使用Django 1.6.2 .

  • 49

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


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

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

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

    • UserAdmin 使用 UserChangeForm 作为修改对象时使用的表单,而该对象又使用 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)
    
  • 3

    当我尝试在创建表单中添加自定义字段时,cesc的答案对我不起作用 . 也许它自1.6.2以来发生了变化?无论哪种方式,我发现将字段添加到两个字段集,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)
    
  • 98

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

    Ticket #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)
    
  • 0

    另一个类似的解决方案(Took from here):

    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)
    

相关问题