Использование 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 63

5 ответов:

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


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

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

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

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

ответ Нико был чрезвычайно полезен, но я обнаружил, что 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)