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

时间:2020-12-31 19:17:52

From the Django.Contrib.Auth docs:

从Django.Contrib。身份验证文档:

Extending Django’s default User If you’re entirely happy with Django’s User model and you just want to add some additional profile information, you can simply subclass django.contrib.auth.models.AbstractUser and add your custom profile fields. This class provides the full implementation of the default User as an abstract model.

扩展Django的默认用户,如果您对Django的用户模型非常满意,并且您只想添加一些附加的概要信息,那么您可以简单地将Django . managed .models子类化。AbstractUser并添加自定义配置文件字段。该类提供了默认用户作为抽象模型的完整实现。

Said and done. I created a new model like below:

所说的和所做的。我创建了一个新模型,如下所示:

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

This shows up in admin almost like Django's standard User. However, the most important difference in admin is that the password-(re)set field is not present, but a normal CharField is displayed instead. Do I really have to override stuff in the admin-config to get this to work? If so, how can I do that in somewhat DRY way (i.e. without copying stuff from the Django source... eww...)?

这显示在admin中,几乎与Django的标准用户一样。然而,admin中最重要的区别是不存在密码(re)集字段,而是显示一个正常的CharField。我真的必须重写admin-config中的内容才能让它工作吗?如果是这样的话,我该如何以某种干巴巴的方式(例如,不复制Django源的内容……)恶……)?

4 个解决方案

#1


91  

After digging around the Django source code for a while, I found a working soultion. I am not totally happy with this solution, but it seems to work. Feel free to suggest better solutions!

在研究了Django源代码一段时间之后,我找到了一个有用的灵魂。我对这个解决方案不是很满意,但它似乎起作用了。请随意提出更好的解决方案!


Django uses UserAdmin to render the nice admin look for User model. By just using this in our admin.py-file, we can get the same look for our model.

Django使用UserAdmin来呈现用户模型的漂亮的admin外观。通过在我们的管理中使用这个。py-file,我们可以对模型进行相同的查找。

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

However, this alone is probably not a good solution, since Django Admin will not display any of your special fields. There are two reasons for this:

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

  • UserAdmin uses UserChangeForm as the form to be used when modifying the object, which in its turn uses User as its model.
  • UserAdmin使用UserChangeForm作为在修改对象时使用的表单,在该对象中使用用户作为其模型。
  • UserAdmin defines a formsets-property, later used by UserChangeForm, which does not include your special fields.
  • UserAdmin定义了一个formsets-property, UserChangeForm稍后使用,它不包含您的特殊字段。

So, I created a special change-form which overloads the Meta inner-class so that the change form uses the correct model. I also had to overload UserAdmin to add my special fields to the fieldset, which is the part of this solution I dislike a bit, since it looks a bit ugly. Feel free to suggest improvements!

因此,我创建了一个特殊的变更表单,它重载元内部类,以便变更表单使用正确的模型。我还必须重载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)

#2


45  

nico's answer has been extremely helpful but I found Django still references the User model when creating a new user.

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

Ticket #19353 references this problem.

票号19353引用了这个问题。

In order to fix it i had to make a few more additions to admin.py

为了修复它,我必须向admin.py添加更多的内容

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)

#3


29  

A simpler solution, admin.py:

一个更简单的解决方案,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 will correctly reference MyUser model for creation and modification. I'm using Django 1.6.2.

Django将正确地引用MyUser模型来创建和修改。我使用Django 1.6.2。

#4


1  

cesc's answer wasn't working for me when I attempted to add a custom field to the creation form. Perhaps it's changed since 1.6.2? Either way, I found adding the field to both fieldsets and add_fieldsets did the trick.

当我尝试向创建表单添加自定义字段时,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)

#1


91  

After digging around the Django source code for a while, I found a working soultion. I am not totally happy with this solution, but it seems to work. Feel free to suggest better solutions!

在研究了Django源代码一段时间之后,我找到了一个有用的灵魂。我对这个解决方案不是很满意,但它似乎起作用了。请随意提出更好的解决方案!


Django uses UserAdmin to render the nice admin look for User model. By just using this in our admin.py-file, we can get the same look for our model.

Django使用UserAdmin来呈现用户模型的漂亮的admin外观。通过在我们的管理中使用这个。py-file,我们可以对模型进行相同的查找。

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

However, this alone is probably not a good solution, since Django Admin will not display any of your special fields. There are two reasons for this:

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

  • UserAdmin uses UserChangeForm as the form to be used when modifying the object, which in its turn uses User as its model.
  • UserAdmin使用UserChangeForm作为在修改对象时使用的表单,在该对象中使用用户作为其模型。
  • UserAdmin defines a formsets-property, later used by UserChangeForm, which does not include your special fields.
  • UserAdmin定义了一个formsets-property, UserChangeForm稍后使用,它不包含您的特殊字段。

So, I created a special change-form which overloads the Meta inner-class so that the change form uses the correct model. I also had to overload UserAdmin to add my special fields to the fieldset, which is the part of this solution I dislike a bit, since it looks a bit ugly. Feel free to suggest improvements!

因此,我创建了一个特殊的变更表单,它重载元内部类,以便变更表单使用正确的模型。我还必须重载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)

#2


45  

nico's answer has been extremely helpful but I found Django still references the User model when creating a new user.

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

Ticket #19353 references this problem.

票号19353引用了这个问题。

In order to fix it i had to make a few more additions to admin.py

为了修复它,我必须向admin.py添加更多的内容

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)

#3


29  

A simpler solution, admin.py:

一个更简单的解决方案,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 will correctly reference MyUser model for creation and modification. I'm using Django 1.6.2.

Django将正确地引用MyUser模型来创建和修改。我使用Django 1.6.2。

#4


1  

cesc's answer wasn't working for me when I attempted to add a custom field to the creation form. Perhaps it's changed since 1.6.2? Either way, I found adding the field to both fieldsets and add_fieldsets did the trick.

当我尝试向创建表单添加自定义字段时,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)