Использование Django auth UserAdmin для пользовательской модели пользователя

С Джанго.ВНО.Проверка подлинности документов:

расширение пользователя Django по умолчанию Если вы полностью довольны пользовательской моделью Django, и вы просто хотите добавить дополнительную информацию о профиле, вы можете просто подкласс django.contrib.auth.models.AbstractUser и добавьте настраиваемые поля профиля. Этот класс предоставляет полную реализацию пользователя по умолчанию в качестве абстрактной модели.

сказано и сделано. Я создал новую модель, как ниже:

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

Это появляется в admin почти как стандарт Django User. Однако самое важное различие в admin заключается в том, что поле password-(re)set отсутствует, но вместо него отображается обычное CharField. Мне действительно нужно переопределить материал в admin-config, чтобы заставить это работать? Если да, то как я могу сделать это несколько сухим способом (т. е. без копирования материала из источника Django... фуу...)?

5 ответов


покопавшись в исходном коде Django некоторое время, я нашел рабочую soultion. Я не совсем доволен этим решением, но, похоже, оно работает. Не стесняйтесь предлагать лучшие решения!


Django использует UserAdmin чтобы сделать хороший админ искать User - модели. Просто используя это в нашем admin.py-файл, мы можем получить такой же взгляд для нашей модели.

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

однако это само по себе, вероятно, не является хорошим решением, так как Django Admin не будет отображаться любое из ваших специальных полей. Этому есть две причины:--13-->

  • UserAdmin использует UserChangeForm как бланк будет использоваться при изменении объекта, который в свою очередь использует User в качестве модели.
  • UserAdmin определяет formsets-свойство, позже используемое UserChangeForm, который не включает ваши специальные поля.

Итак, я создал специальную форму изменения, которая перегружает мета-внутренний класс, так что форма изменения использует правильную модель. Мне тоже пришлось перегрузка 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)

ответ Нико был очень полезен, но я обнаружил, что Django по-прежнему ссылается на модель пользователя при создании нового пользователя.

авиабилет #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)