Ошибка пользовательской модели 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'
Дело в том, что мне нужна эта модель, управляемая сайтом администратора, чтобы иметь тот же процесс создания, что и с исходной моделью пользователя (двухэтапный процесс с проверкой пароля).
Ответы
Ответ 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
, и управлять ими с помощью модели пользователя. Это будет работать каждый раз, если я правильно подумаю.