8

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_MODELto mainfolder.app.MyUserI'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..

4

2 回答 2

10

TL;DR:使用以下答案末尾的解决方案部分的代码。

更长的解释:你看,从Django 1.5UserAdmin开始,子类化 Django以能够与可交换的用户模型交互是不够的:你还需要覆盖相应的表单。

如果你跳转到django.contrib.auth.adminsource,你会看到UserAdmin's formandadd_form有这些值:

# django/contrib/auth/admin.py
class UserAdmin(admin.ModelAdmin):
    ...
    form = UserChangeForm
    add_form = UserCreationForm 

这指向我们尊重可交换用户模型的表单django.contrib.auth.forms

# 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.

解决方案:因此,您应该遵循一个已经存在的很好的答案不要忘记投票!)归结为:

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)

希望这将在 Django 的未来版本中得到修复(这是错误跟踪器中的相应票证)。

于 2013-05-06T11:27:17.573 回答
2

当你说你设置时AUTH_USER_MODEL = 'app.MyUser',我假设你的应用程序位于MyUser类,有一个结构,perharps,像这样:

在 app/ 目录中:init .py 和 models.py 等等。

所以在models.py里面你有init .pyMyUser里面的and :

from models import MyUser

于 2013-05-05T20:29:49.837 回答