web-dev-qa-db-ja.com

カスタムユーザーモデルにDjango auth UserAdminを使用する

Django.Contrib.Authドキュメント から:

Djangoのデフォルトユーザーの拡張Djangoのユーザーモデルに完全に満足していて、追加のプロファイル情報を追加したい場合は、単にサブクラスDjango.contrib.auth.models.AbstractUserそして、カスタムプロファイルフィールドを追加します。このクラスは、デフォルトモデルの完全な実装を抽象モデルとして提供します。

言ってやった。以下のような新しいモデルを作成しました:

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

これは、Djangoの標準Userとほぼ同じようにadminに表示されます。ただし、adminの最も重要な違いは、password-(re)setフィールドは存在しないが、代わりに通常のCharFieldが表示されることです。これを機能させるには、本当にadmin-configの内容をオーバーライドする必要がありますか?もしそうなら、どうすればそれをややDRY方法で(つまり、Django source ... eww ...)

72
nip3o

Django=ソースコードをしばらく調べた後、動作するsoultionを見つけました。このソリューションに完全に満足しているわけではありませんが、動作しているようです。


DjangoはUserAdminを使用して、UserモデルのNice管理ルックをレンダリングします。 admin.py-ファイルでこれを使用するだけで、モデルの外観を同じにすることができます。

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

ただし、Django Adminは特別なフィールドを表示しません。これには2つの理由があります。

  • UserAdminは、オブジェクトを変更するときに使用するフォームとしてUserChangeFormを使用し、そのモデルとしてUserを使用します。
  • UserAdminは、後でformsetsで使用されるUserChangeForm-プロパティを定義します。これには特別なフィールドは含まれません。

そこで、Meta内部クラスをオーバーロードする特別な変更フォームを作成して、変更フォームが正しいモデルを使用するようにしました。また、UserAdminをオーバーロードして特別なフィールドをフィールドセットに追加しなければなりませんでした。改善点をお気軽にご提案ください!

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)
114
nip3o

nicoの答えは非常に役に立ちましたが、新しいユーザーを作成するときにDjangoはまだUserモデルを参照しています。

チケット #1935 はこの問題を参照しています。

それを修正するために、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)
54
kdh454

より単純なソリューション、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。

41
cesc

作成フォームにカスタムフィールドを追加しようとしたときに、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)
5
aidnani8

別の同様のソリューション( ここから探す ):

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)
1