Подтвердить что ты не робот

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

Из Django.Contrib.Auth docs:

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

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

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

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

4b9b3361

Ответ 1

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


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

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

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

  • UserAdmin использует UserChangeForm как форму, которая будет использоваться при модификации объекта, который в свою очередь использует User в качестве своей модели.
  • UserAdmin определяет formsets -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)

Ответ 2

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

Ticket # 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)

Ответ 3

Более простое решение:

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.

Ответ 4

Ответ 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)