[django] 커스텀 사용자 모델에 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에서 가장 중요한 차이점은 password- (re) set 필드가 없지만 대신 일반 CharField가 표시된다는 것입니다. 이 작업을 수행하려면 admin-config의 항목을 재정의해야합니까? 그렇다면 어떻게 DRY 방식으로이를 수행 할 수 있습니까 (예 : Django 소스에서 복사하지 않고 … eww …)?



답변

Django 소스 코드를 잠시 살펴본 후 작동하는 영혼을 발견했습니다. 이 솔루션에 완전히 만족하지는 않지만 작동하는 것 같습니다. 더 나은 솔루션을 자유롭게 제안하십시오!


Django는 모델에 UserAdmin대한 멋진 관리자 모양을 렌더링하는 데 사용 합니다 User. admin.py-파일 에서 이것을 사용함으로써 우리 모델에 대해 동일한 모습을 얻을 수 있습니다.

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

그러나 Django Admin은 특수 필드를 표시하지 않기 때문에 이것만으로는 좋은 해결책이 아닐 수 있습니다. 여기에는 두 가지 이유가 있습니다.

  • UserAdmin용도 UserChangeForm는 선회 용도의 물체 수정할 때 형태로 사용될 수 User는 모델로한다.
  • UserAdminformsets나중에에서 사용 하는 -property를 정의 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)


답변

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)


답변

더 간단한 솔루션 인 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를 사용하고 있습니다.


답변

생성 양식에 사용자 정의 필드를 추가하려고 할 때 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)


답변

또 다른 유사한 솔루션 ( 여기에서 가져옴 ) :

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)


답변

다음과 같이하십시오.

from django.contrib import admin
from .models import MyUser

admin.site.register(MyUser, admin.ModelAdmin)

그게 다야. MyUser 모델의 모든 필드가 표시됩니다.표시 할 UserAdmin의 필드 목록은 하드 코딩되었지만 (소스 코드 참조) ModelAdmin은 그렇지 않습니다. 유연합니다.


답변