【问题标题】:Custom User Model error自定义用户模型错误
【发布时间】:2013-04-29 10:13:17
【问题描述】:

我正在尝试在 Django 中设置我的自定义用户模型。原因是我想使用电子邮件作为用户名,并完全删除用户名字段。我遇到了一个错误,我无法弄清楚。

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']

我疯狂地用谷歌搜索,但没有找到太多关于此错误消息的页面。我找到了一些页面,其中包含有关如何解决它的建议,但没有一个建议对我有用。

我的代码:我设置了自定义用户模型。我已经在 settings.py 中声明了自定义用户模型AUTH_USER_MODEL = 'app.MyUser'。我还设置了一个自定义 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()

我尝试向不同类型的 UserAdmins 声明,但没有任何区别,我尝试的第一个是;

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)

我已经注释掉了add_form 和form 这两个属性,因为它们引发了一些我想稍后再讨论的表单错误。

在阅读了可能的修复here 之后,创建了第二个 UserAdmin。但这无济于事。

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)

我也尝试过删除数据库中的所有表,但没有成功。

我会永远感激任何看到这个问题的人。如果有人要解决这个问题,我会尽力说服我的妻子以给我解决方案的阿凡达命名我们的长子,这样我就可以继续过我的生活。

编辑: 我尝试将AUTH_USER_MODEL设置为mainfolder.app.MyUser我确定“主文件夹”在pythonpath上。应用中的 init.py 应该是正确的。新的 settings.py 给出了以下服务器错误; 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.一个新线索我不知道怎么解读..

【问题讨论】:

  • 你的应用名称是'app'吗?
  • 首先,不要惊慌,我们会解决这个问题的。 :) 你什么时候看到错误?如果禁用管理员,错误会消失吗?你试过一步步调试吗?
  • @Ivan 好的,很高兴听到 :) 在 /admin 上输入用户凭据并按“登录”后会发生错误。如果我关闭管理员,我希望错误会消失,现在没有机会测试,但是与管理员无关的页面可以正常工作。
  • @Rohan 不,我在发帖时出于匿名目的稍微更改了代码,可能有点偏执,但无论如何。
  • 我认为我们可以将问题缩小到您的MyUserAdmin 表单。当您提交问题时,您的AUTH_USER_MODEL 已正确声明。你试过this fix吗?

标签: django django-models django-admin django-1.5


【解决方案1】:

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

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

如果您跳转到django.contrib.auth.admin source,您会看到UserAdmin's form 和add_form 具有以下值:

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

forms in 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.

解决方案:因此,您应该关注一个已经存在的answer(别忘了投票!)归结为: p>

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 的未来版本中得到修复(这是错误跟踪器中的 corresponding ticket)。

【讨论】:

  • 亲爱的@Ivan,老实说,我无法相信你是多么善良,花费了你这么多的时间和精力来帮助我。你的努力真的很感激!我希望有某种英雄徽章,每个用户只能发放一次。如果有这样的东西,我会把徽章给你!我今天没有时间解决这个问题,我所尝试的只是从您的解决方案中复制表单和 UserAdmin。这引发了一条错误消息,但它似乎源于用户模型中的所有字段尚未在更改/创建表单中声明的​​事实。 Lt u knw tmrw
  • 非常感谢!我可能应该给你best comment I ever received 徽章。 :)))
  • 我不知道,这可能不是写这篇文章的最佳地点,但不知怎的,我可以把你描绘成一个非常成熟的人,他重视周围的人,知道如何关心他们。你让我想起了我的祖父。
  • 谢谢你的好话,但你对我的评价很高!但我也很好奇你,因为你的慷慨,帮助一个完全陌生的人解决他的问题:)。正是像你这样的人让世界变得更美好,我敢肯定!很抱歉昨天没有给你回电话,但没想到一整天都在工作。今天是挪威的假期(我想还有很多其他国家),所以这意味着 python,万岁 :) 你的回答解决了我的问题,所以再次感谢你!
  • 嘿,昨天我们也度过了一个假期,但我和父亲一起喝了伏特加,并谈论了我们在战争中战斗和/或死亡的亲戚。其实,过去我在非商业的项目中涉足很深,对未来也有一些规划。这是我帮助推广的writer 中的some works。再次感谢您的客气话! )))))
【解决方案2】:

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

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

所以在 models.py 中你有 MyUser 和 init.py:

from models import MyUser

【讨论】:

  • 感谢您花时间查看我的问题@user1808134。是的,该应用确实包含 init.py。我没有在其中声明任何内容,但是在看到您的回答后现在就这样做了。我插入了__all__ = ['views','tests', 'static','models','admin',]但无济于事,在管理页面上按“登录”时出现同样的错误(PS。也尝试在 init.py 文件中使用 from models import MyUser
  • 我尝试将AUTH_USER_MODEL设置为mainfolder.app.MyUser我确定“主文件夹”在pythonpath上。我仍然有上面的 init.py。新的 settings.py 给出了以下服务器错误; 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.这有什么提示吗?
  • 我对这个问题进行了一些研究,但没有发现任何启发性 =/ 上次我使用新的 Django 自定义身份验证时,我已按照 django 文档中的说明进行操作,我知道它并不多。
  • 感谢您的宝贵时间。仅供参考,我得到了上述答案的帮助。
猜你喜欢
  • 1970-01-01
  • 2017-07-13
  • 2021-10-21
  • 1970-01-01
  • 2021-08-21
  • 1970-01-01
  • 1970-01-01
  • 2021-10-27
  • 1970-01-01
相关资源
最近更新 更多