I'm trying to set up my custom user model in Django. The reason is that I want to use email as the username, and remove the username field entirely. I've run into a error, that I just can't figure out.
Manager isn't available; User has been swapped for 'app.MyUser'
Exception Location: .../django/db/models/manager.py in __get__, line 256
Python Version: 2.7.3
Python Path:
[...project specific files,
'/usr/lib/python2.7',
'/usr/lib/python2.7/plat-linux2',
'/usr/lib/python2.7/lib-tk',
'/usr/lib/python2.7/lib-old',
'/usr/lib/python2.7/lib-dynload',
'/usr/local/lib/python2.7/dist-packages',
'/usr/lib/python2.7/dist-packages',
'/usr/lib/python2.7/dist-packages/PIL',
'/usr/lib/python2.7/dist-packages/gtk-2.0',
'/usr/lib/pymodules/python2.7',
'/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode']
I've googled like crazy, but haven't found too many pages about this error message. I have found some pages, with suggestions on how to solve it, but none of the suggestions have worked for me.
My code: I've set the custom user model. I have declared the custom user model AUTH_USER_MODEL = 'app.MyUser'
in settings.py. I have also set up a custom UserManager:
class MyUserManager(BaseUserManager):
def create_user(self, email, password=None):
"""
Creates and saves a User with the given email. Note that none of the optional fields gets values in the creation. These fields will have to be filled out later on.
"""
if not email:
raise ValueError('Users must have an email address')
user = self.model(email=MyUserManager.normalize_email(email))
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, password=None):
"""
Creates and saves a superuser with the the above mentioned attributes
"""
user = self.create_user(email, password=password)
user.is_admin = True
user.save(using=self._db)
return user
class MyUser(AbstractBaseUser, PermissionsMixin):
"""
Custom made User model. No username, instead email is used as unique field and index
"""
Genders = (('M', 'Man'), ('K', 'Woman'))
FirstName = models.CharField(max_length=30)
LastName = models.CharField(max_length=40)
Gender = models.CharField(max_length=2, choices=Genders, default='K')
email = models.EmailField(verbose_name='email address', max_length=255, unique=True, db_index=True,)
twitter = models.CharField(max_length=30)
is_admin = models.BooleanField(default=False)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
def get_full_name(self):
# The user is identified by their email address
return self.email
def get_short_name(self):
# The user is identified by their email address
return self.email
def __unicode__(self):
return self.email
objects = MyUserManager()
I've tried to declare to different types of UserAdmins, none of which is making any difference,the first one I tried was;
class MyUserAdmin(UserAdmin):
# The forms to add and change user instances
#form = UserChangeForm
#add_form = FrontpageRegistrationForm
list_display = ('email', 'FirstName', 'LastName', 'Gender', 'twitter')
list_filter = ()
add_fieldsets = ((None, {'classes': ('wide',),'fields': ('email', 'password1', 'password2')}),)
search_fields = ('email',)
ordering = ('email',)
filter_horizontal = ()
admin.site.register(MyUser, MyUserAdmin)
I've commented out the two attributes add_form
and form
because they raised some form errors I wanted to get back to at a later point.
The second UserAdmin was made, after reading about a possible fix here. This didn't help the situation though;
class MyUserAdmin(admin.ModelAdmin):
# The forms to add and change user instances
#form = UserChangeForm
add_form = FrontpageRegistrationForm
add_fieldsets = ((None, {'classes': ('wide',),'fields': ('email', 'password1', 'password2')}),)
def get_fieldsets(self, request, obj=None):
if not obj:
return self.add_fieldsets
return super(MyUserAdmin, 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(MyUserAdmin, self).get_form(request, obj, **defaults)
I've also tried deleting all tables in the db with no luck.
I would be eternally greatful to anyone who even looks at the problem. And if any one were to solve this, I would try my best to talk my wife into naming our firstborn after the Avatar that gave me a solution so that I could go on living my life.
EDIT:
I tried setting the AUTH_USER_MODEL
to mainfolder.app.MyUser
I'm sure the "mainfolder" is on the pythonpath. init.py in the app should be correct. The new settings.py gave the following server error; auth.user: AUTH_USER_MODEL is not of the form 'app_label.app_name'.admin.logentry: 'user' has a relation with model smartflightsearch.SFSdb.MyUser, which has either not been installed or is abstract.registration.registrationprofile: 'user' has a relation with model, which has either not been installed or is abstract.
A new clue I don't know how to interpret..
TL;DR: Use the code from the Solution part at the end of the following answer.
Longer explanation: You see, as of Django 1.5, it's not enough to subclass Django's UserAdmin
to be able to interact with swappable user models: you need to override respective forms as well.
If you jump to django.contrib.auth.admin
source, you'll see that the UserAdmin's
form
and add_form
have these values:
# django/contrib/auth/admin.py
class UserAdmin(admin.ModelAdmin):
...
form = UserChangeForm
add_form = UserCreationForm
Which point us to forms in django.contrib.auth.forms
that do not respect swappable user models:
# django/contrib/auth/forms.py
class UserCreationForm(forms.ModelForm):
...
class Meta:
model = User # non-swappable User model here.
class UserChangeForm(forms.ModelForm):
...
class Meta:
model = User # non-swappable User model here.
Solution: So, you should follow a great already existing answer (don't forget to vote it up!) which boils down to this:
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()
class MyUserAdmin(UserAdmin):
form = MyUserChangeForm
add_form = MyUserCreationForm
admin.site.register(MyUser, MyUserAdmin)
Hopefully, this would be fixed in the future releases of Django (here's the corresponding ticket in the bug tracker).
When you said you set AUTH_USER_MODEL = 'app.MyUser'
I'm assuming your app where is located the MyUser
class, have a structure, perharps, like this:
inside the app/ dir: init.py and models.py and stuff..
so inside the models.py you have the MyUser
and inside the init.py:
from models import MyUser
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With