커스텀 사용자 모델에 Django auth UserAdmin 사용


82

로부터 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 ...)?

답변:


135

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)

큰! 이것이 바로 제가 찾던 것입니다. 저는 AbstractUser를 사용하여 커스텀 사용자 모델로 똑같이하고 있습니다. 이 솔루션은 훌륭하게 작동하며 일부 사용자 정의 (필드 숨기기, '개인 정보'에 'some_extra_data'추가)도 좋겠지 만 지금은 하루를 마무리했습니다. 덕분에 @nico
Dachmt

UserAdmin 필드 세트의 오버로드가 추악합니까? 효과가있다. 감사.
allcaps 2013-06-09

6
또한 @ kdh454의 답변에 따라 사용자 생성 양식을 재정의해야합니다.
Thane Brimhall 2013

이것은 완벽하고 전혀 지저분하지 않습니다. 장고 문서이 문서 포인트 : docs.djangoproject.com/en/2.0/topics/auth/customizing/...는 ... 그러나 나는 그것이 일부 사용자 외래 키 제약 조건에 대해 불평, 그 작업을 만들 수 않네. 내 프로젝트에만 관련 될 수 있지만 솔루션은 작동합니다!
Vladimir Marton

57

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)

귀하의 솔루션은 저에게 완벽하게 작동했습니다. 감사합니다!
guinunez

3
1.6부터 호출에 forms.ValidationError두 번째 인수가 있습니다. code='duplicate_username': github.com/django/django/blob/1.6/django/contrib/auth/… 또한 1.6.5에서 시도했고 어떤 이유로 든 전혀 재정의 할 필요가 없었고 UserChangeForm변경 양식이 내 사용자 정의 필드에서 잘 작동했습니다. 이유를 설명 할 수 없습니다. 이 때문에의 일을하지 말았어야 것 같아 UserChangeForm클래스 가진 model = User현재 : github.com/django/django/blob/1.6.5/django/contrib/auth/...

2
FYI 티켓 # 19353 이 수정되었습니다. 이는 본질적으로 솔루션이 중복 될 수 있음을 의미합니다. @ nip3o의 솔루션을 사용하면 좋을 것입니다.
kstratis

50

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


이유는 모르겠지만 시도 할 때 "TypeError : +에 대한 지원되지 않는 피연산자 유형 : 'NoneType'및 'tuple'"이 계속 표시됩니다.
Chase Roberts

난 당신이 UserAdmin.fieldsets를 검사하고보고하는 것이 좋습니다 경우의 없음
로물로 Collopy

1
이것이 가장 최신의 답변이며 받아 들여 져야합니다
brillout

1
대신 None문자열을 입력 할 수 있으며 관리자 양식의 섹션 제목으로 사용됩니다
Guillaume Lebreton

@brillout에 동의하고 이것이 최선의 답변이라는 것을 알았습니다. 추가하려면이 오류가 발생할 수 있습니다. 이는 의미가 있습니다 (Python 3.8, Django 3) :ERRORS: <class 'users.admin.CustomerUserAdmin'>: (admin.E005) Both 'fieldsets' and 'fields' are specified.
nicorellius

9

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

2

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

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

다음과 같이하십시오.

from django.contrib import admin
from .models import MyUser

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

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


권장하지 않습니다. 이것은 ModelAdmin사용자 정의 된 것이 아니라 기본값을 사용합니다 UserAdmin. 결과는 엉망입니다.
dqd
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.