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

Ошибка пользовательской модели Django 1.5. "Менеджер недоступен, пользователь был заменен"

Я расширяю пользовательскую модель django, как описано в dev doc. Я не буду хранить большинство исходных функций модели пользователя, поэтому я расширяю класс AbstractUser. Я определил в settings.py:

AUTH_USER_MODEL = 'myapp.CustomUser'

Мой класс пользователя:

class CustomUser(AbstractUser):
  custom_field = models.ForeignKey('OtherModel')
  objects = UserManager()

Кажется, что все работает нормально, но когда я пытаюсь заставить его управлять сайтом администратора:

admin.site.register(CustomUser, UserAdmin)

Я получаю эту ошибку на странице создания пользовательского CustomUser (после проверки формы подтверждения пароля):

AttributeError: Manager isn't available; User has been swapped for 'myapp.CustomUser'

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

4b9b3361

Ответ 1

Вам нужно только изменить форму для добавления пользователя (перезаписать clean_username и изменить User на get_user_model()

Полный рабочий пример (если вы унаследовали от AbstractUser)

from django.contrib.auth import get_user_model
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.forms import UserCreationForm, UserChangeForm


class MyUserChangeForm(UserChangeForm):

    class Meta:
        model = get_user_model()

class MyUserCreationForm(UserCreationForm):

    class Meta:
        model = get_user_model()

    def clean_username(self):
        username = self.cleaned_data["username"]
        try:
            get_user_model().objects.get(username=username)
        except get_user_model().DoesNotExist:
            return username
        raise forms.ValidationError(self.error_messages['duplicate_username'])

class MyUserAdmin(UserAdmin):
    form = MyUserChangeForm
    add_form = MyUserCreationForm
    fieldsets = (
        (None, {'fields': [('username', 'password'),]}),
        (_('Personal info'), {'fields': ('first_name', 'last_name', 'email')}),
        (_('Permissions'), {'fields': ('is_active', 'is_staff', 'is_superuser',
                                   'groups', 'user_permissions')}),
        (_('Important dates'), {'fields': ('last_login', 'date_joined')}),
        )

admin.site.register(MyUser, MyUserAdmin)

Ответ 2

Я боролся с этой ошибкой часами. Для меня мне нужно было удалить все ссылки на

from django.contrib.auth.models import User

а затем замените его на:

from myapp.models import MyUser as User

Предполагается, что ваша пользовательская модель пользователя находится в приложении под названием myapp, и вы вызвали модель MyUser.

Я использую as User, поэтому мне не нужно менять, где мой существующий код ссылается на объект User из django.contrib.auth.models.

Удачи!

Алан

@aviars

Ответ 3

Вероятно, вам стоит посмотреть пример полный в официальной документации:

https://docs.djangoproject.com/en/dev/topics/auth/customizing/#a-full-example

Есть некоторые непокрытые вопросы (например, обработка разрешений), но, по крайней мере, это работает.

Ответ 4

Из Django docs:

Вы также должны определить пользовательский менеджер для своей модели пользователя.

Ответ 5

Подкласс AbstractUser уже обрабатывает objects = UserManager() для вас (этот код в github в строке 327). Вам больше не нужно определять его в своей модели.

Я не уверен, почему он пришел с этой ошибкой. Но ниже config, похоже, работает для меня с последней версией Dev.

Model.py:

class CustomUser(AbstractUser):
  custom_field = models.ForeignKey('OtherModel')
  # remove : objects = UserManager()

Ответ 6

Я нашел решение: Я не использую UserAdmin для регистрации CustomUser на сайте администратора, я использую собственный ModelAdmin.

class CustomUserAdmin(admin.ModelAdmin):

  add_form = CustomUserCreationAdminForm
  add_fieldsets = (
    (None, {
        'classes': ('wide',),
        'fields': ('username', 'password1', 'password2')}
    ),
  )
  def get_fieldsets(self, request, obj=None):
    if not obj:
        return self.add_fieldsets
    return super(CustomUserAdmin, self).get_fieldsets(request, obj)

  def get_form(self, request, obj=None, **kwargs):
    defaults = {}
    if obj is None:
        defaults.update({
            'form': self.add_form,
            'fields': admin.util.flatten_fieldsets(self.add_fieldsets),
        })
    defaults.update(kwargs)
    return super(CustomUserAdmin, self).get_form(request, obj, **defaults)

Поскольку я хочу иметь форму создания, отличную от формы обновления, я переопределяю функцию get_form для администратора модели, как это сделано в UserAdmin django code. Я также создал пользовательскую форму создания для моего пользовательского пользователя: CustomUserCreationForm

Я получил ответ в списке рассылки django-users, который может быть лучше моего: Отмените регистрацию исходного класса пользователя с сайта администратора и затем зарегистрируйте CustomUser с UserAdmin:

admin.site.unregister(User)
admin.site.register(CustomUser, UserAdmin)

Не тестировалось.

EDIT: это последнее решение не работает

Привет

Ответ 7

UserAdmin уже зарегистрирован для управления User, в конце файла contrib/auth/admin.py

admin.site.register(User, UserAdmin)

Учитывая, что вы хотите зарегистрировать UserAdmin с помощью CustomUser, я думаю, вам сначала нужно отменить регистрацию пары User/UserAdmin:

admin.site.unregister(User)

затем зарегистрируйте свою новую модель. Учитывая отсутствие контроля в порядке загрузки модуля, вы можете создать класс, полученный из UserAdmin, и управлять ими с помощью модели пользователя. Это будет работать каждый раз, если я правильно подумаю.