AUTH_USER_MODEL 指的是尚未安装和创建的模型 .. AbstractUser 模型无法登录

Posted

技术标签:

【中文标题】AUTH_USER_MODEL 指的是尚未安装和创建的模型 .. AbstractUser 模型无法登录【英文标题】:AUTH_USER_MODEL refers to model .. that has not been installed and created AbstractUser models not able to login 【发布时间】:2013-01-19 21:52:38 【问题描述】:

AUTH_USER_MODEL 错误已在 EDIT3 中解决。通过表单创建用户时,密码仍然不会保存。

我正在使用 Django 1.5 玩弄新的用户覆盖/扩展功能,我无法通过我的注册表单注册新用户 - 只能通过管理员。通过注册表单注册时,我收到以下错误:

Manager isn't available; User has been swapped for 'poker.PokerUser'

models.py:

class PokerUser(AbstractUser):
    poker_relate = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, blank=True)
    token = models.EmailField()
    USER_CHOICES = (
        ('1', 'Staker'),
        ('2', 'Horse')
    )
    user_type = models.CharField(choices=USER_CHOICES, max_length=10)
    username1 = models.CharField(null=True, blank=True, max_length=40)
    username2 = models.CharField(null=True, blank=True, max_length=40)
    username3 = models.CharField(null=True, blank=True, max_length=40)
    username4 = models.CharField(null=True, blank=True, max_length=40)
    username5 = models.CharField(null=True, blank=True, max_length=40)

PokerUserForm模特:

class PokerUserForm(UserCreationForm):
    class Meta:
        model = PokerUser
        fields = ('username','password1','password2','email','user_type','token','username1','username2','username3','username4','username5',)

我尝试将PokerUserForm 模型中的模型更改为使用get_user_model(),而不是通过设置model = get_user_model() 而不是model = PokerUser 来显式定义模型,但随后我收到以下错误:

django.core.exceptions.ImproperlyConfigured: AUTH_USER_MODEL refers to model 'poker.PokerUser' that has not been installed

我的AUTH_USER_MODEL 设置在我的settings.py 中,如下所示:

AUTH_USER_MODEL = 'poker.PokerUser'

开始吧 - 我在views.py 中的注册视图:

def UserRegistration(request):
    player = PokerUser()

    if request.method == 'POST':
        form = PokerUserForm(request.POST, instance=player)
        if form.is_valid():
            player.email_address = form.cleaned_data['email']
            player.user_type = form.cleaned_data['user_type']
            # if player is staker, token is their own email. otherwise their token is their staker's email and
            # their relation is their staker
            if player.user_type == '1' or player.user_type == 'staker':
                player.token = player.email_address
            else:
                player.token = form.cleaned_data['token']
                staker = PokerUser.objects.get(email=player.token)
                player.poker_relate = staker
            player.save()
            return HttpResponseRedirect('/')
    else:
        form = PokerUserForm()
    initialData = 'form': form
    csrfContext = RequestContext(request, initialData)
    return render_to_response('registration/register.html', csrfContext)

EDIT1:

According to the docs,UserCreationForm 必须重新创建以用于自定义用户类。

我将整个UserCreationForm 覆盖如下:

class UserCreationForm(forms.ModelForm):
    """
    A form that creates a user, with no privileges, from the given username and
    password.
    """
    error_messages = 
        'duplicate_username': _("A user with that username already exists."),
        'password_mismatch': _("The two password fields didn't match."),
        
    username = forms.RegexField(label=_("Username"), max_length=30,
        regex=r'^[\w.@+-]+$',
        help_text=_("Required. 30 characters or fewer. Letters, digits and "
                    "@/./+/-/_ only."),
        error_messages=
            'invalid': _("This value may contain only letters, numbers and "
                         "@/./+/-/_ characters."))
    password1 = forms.CharField(label=_("Password"),
        widget=forms.PasswordInput)
    password2 = forms.CharField(label=_("Password confirmation"),
        widget=forms.PasswordInput,
        help_text=_("Enter the same password as above, for verification."))

    class Meta:
        model = PokerUser
        fields = ('username','password1','password2','email','user_type','token','username1','username2','username3','username4','username5',)

    def clean_username(self):
        # Since User.username is unique, this check is redundant,
        # but it sets a nicer error message than the ORM. See #13147.
        username = self.cleaned_data["username"]
        try:
            PokerUser.objects.get(username=username)
        except PokerUser.DoesNotExist:
            return username
        raise forms.ValidationError(self.error_messages['duplicate_username'])

    def clean_password2(self):
        password1 = self.cleaned_data.get("password1")
        password2 = self.cleaned_data.get("password2")
        if password1 and password2 and password1 != password2:
            raise forms.ValidationError(
                self.error_messages['password_mismatch'])
        return password2

    def save(self, commit=True):
        user = super(UserCreationForm, self).save(commit=False)
        user.set_password(self.cleaned_data["password1"])
        if commit:
            user.save()
        return user

这能够解决这个错误:

The Manager isn't available; User has been swapped for 'poker.PokerUser'

现在,用户已创建但无法登录。当我在管理员中检查用户时,所有信息似乎都是正确的,除了密码。在管理员中手动添加密码似乎无法正常工作。尽管如此,通过管理员添加用户仍然可以正常工作。

编辑 2:

我仍然无法以通过注册表单创建的任何 AbstractUser 模型登录。如上所述,我已经完全覆盖了UserCreationForm,并且无法实施 get_user_model() 出现此错误:

AUTH_USER_MODEL refers to model 'poker.PokerUser' that has not been installed

get_user_model() 的 Django 代码是:

 def get_user_model():
    "Return the User model that is active in this project"
    from django.conf import settings
    from django.db.models import get_model

    try:
        app_label, model_name = settings.AUTH_USER_MODEL.split('.')
    except ValueError:
        raise ImproperlyConfigured("AUTH_USER_MODEL must be of the form 'app_label.model_name'")
    user_model = get_model(app_label, model_name)
    if user_model is None:
        raise ImproperlyConfigured("AUTH_USER_MODEL refers to model '%s' that has not been installed" % settings.AUTH_USER_MODEL)
    return user_model

由于我的settings.py 中有AUTH_USER_MODEL = 'poker.PokerUser' 设置,这应该可以工作。我已经通过 Django 控制台验证了这一点:

>>> from django.contrib.auth import get_user_model
>>> settings.AUTH_USER_MODEL
Out[14]: 'poker.PokerUser'
>>> from django.db.models import get_model
>>> app_label, model_name = settings.AUTH_USER_MODEL.split('.')
>>> user_model = get_model(app_label, model_name)
>>> user_model
Out[18]: poker.models.PokerUser

但是,实施仍然无法正常工作。

如果您已经读到这里,谢谢!

EDIT3:

AUTH_USER_MODEL refers to model 'poker.PokerUser' that has not been installed 已修复。我不小心在poker.models 中重新创建了UserCreationForm 而不是registration.forms,所以当我运行分配给poker.PokerUserget_user_model() 时,它无法解析,因为它已经在那个位置。

现在剩下的唯一问题是在创建新用户时,他们的密码不会保存。通过在此处放置打印语句,我已将其缩小为 UserCreationForm 中的一个方法:

def clean_password2(self):
    password1 = self.cleaned_data.get("password1")
    print password1
    password2 = self.cleaned_data.get("password2")
    print password2
    if password1 and password2 and password1 != password2:
        raise forms.ValidationError(
            self.error_messages['password_mismatch'])
    print password2
    return password2

def save(self, commit=True):
    user = super(UserCreationForm, self).save(commit=False)
    user.set_password(self.cleaned_data["password1"])
    print self.cleaned_data["password1"]
    if commit:
        user.save()
    return user

clean_password2 中的print password1print password1 语句显示纯文本密码,但save 方法中的print self.cleaned_data["password1"] 为空白。为什么我的表单数据没有传递给 save 方法?

TL;DR AbstractUser 模型创建在管理员和注册表单中都有效,但只有通过管理员创建的用户才能登录。通过注册表单创建的用户无法登录,并且似乎在没有密码的情况下保存了 - 所有其他信息都已正确保存。

【问题讨论】:

【参考方案1】:

如果您在项目中创建了多个目录来维护结构,请检查您编写的用户模型的目录。 只需在该目录的 init.py 中导入 User 模型即可。

例子:

app directory: 
     app/
       views/
         __init__.py
         views.py
       models/
         __init__.py  ->  from .user_model import User
         user_model.py -> class User(AbstractUser):

就我而言,我通过这种方式得到了解决方案。

【讨论】:

【参考方案2】:

在我的例子中,我覆盖了内置的 User 模型并将导致此问题的类抽象化。因此,在元类中更改 abstract=False 解决了这个问题。

class User(AbstractBaseUser, PermissionMixin):
      email = models.EmailField(max_length=255)

      class Meta:
      abstract = False

【讨论】:

【参考方案3】:

如果您忘记在设置中注册您的应用,可能会发生这种情况。在您的 settings.py 文件中,将您的应用程序的名称添加到 INSTALLED_APPS 列表中。我希望这会有所帮助。

例如,如果您的应用名称是“用户”,它看起来像这样:

INSTALLED_APPS = [
  ......

  'users'
]

【讨论】:

【参考方案4】:

在我的情况下更新,meta 中正确的 app_label 解决了这个问题

class APPUser(AbstractUser):
   password = models.TextField(blank=True)

   class Meta:
     app_label = 'app_auth'
     db_table = "app_user"

【讨论】:

【参考方案5】:

我遇到过几次。一直是进口问题。假设我们有 core/models.py,它实现了一个自定义用户并从另一个文件(比如 Else)导入了一个符号:

from Something import Else

class CustomUser(AbstractBaseUser):
    pass

然后我们有另一个使用 CustomUser 并定义 Else 的文件。让我们称之为 something/models.py:

from core.models import CustomUser

class Else(models.Model):
    pass

class AnotherClass(models.model):
    user = models.ForeignKey(CustomUser)

当 core/models.py 去 import Else 时,它​​会评估 something/models.py 并运行到 AnotherClass 定义中。 AnotherClass 使用 CustomUser,但尚未安装 CustomUser,因为我们正在创建它。所以,它会抛出这个错误。

我通过保持 core/models.py 独立解决了这个问题。它不会从我的其他应用中导入太多内容。

【讨论】:

我是不是因为我是 Python 新手而感到恼火,还是 Python 人通常也对讨厌的导入问题感到恼火?随着项目的发展,不可能跟踪它们! @nakajuice 这个问题几乎是 Django 特刊。用户模型的情况是一场彻底的垃圾火灾,自从我十年前开始使用 django 以来一直如此,它让我感到困惑,它允许这样继续下去。当它不允许你安装用户模型时,因为没有安装用户模型,框架需要足够聪明才能说'等等,这感觉像是一个悖论,让我们尝试一下其他方式' 对我来说,问题是我在进行迁移之前在admin.py 中导入了模型。我从admin.py 中注释掉了代码并运行了迁移,然后一切正常。 @RobJones,您能否提供有关“保持我的 core/models.py 独立的更多详细信息。它不会从我的其他应用程序中导入太多内容。”。【参考方案6】:

好的,我这里有三个问题,所以我将解决所有这些问题,因为我很确定前两个问题会出现在其他人身上。

Manager isn't available; User has been swapped for 'poker.PokerUser'

这是由于使用但未重新创建 UserCreationForm。在 1.5 中使用自定义模型时,一些模型表单是开箱即用的,但必须重新创建。有关文档,请参阅 here。

The Manager isn't available; User has been swapped for 'poker.PokerUser'

虽然我在settings.py 中设置了AUTH_USER_MODEL = 'poker.PokerUser',但我从poker.models 位置调用get_user_model()。您必须从其他位置致电get_user_model()。将我的表单移动到 registration.forms 并从那里调用 get_user_model() 工作正常。

新用户未保存

这只是我的大脑放屁。在我的UserRegistration 模型中,我正在处理表单中的各个字段。当我将这些字段传递回 UserCreationForm 以使用 save() 方法时,我并没有传递密码字段。哎呀!

【讨论】:

以上是关于AUTH_USER_MODEL 指的是尚未安装和创建的模型 .. AbstractUser 模型无法登录的主要内容,如果未能解决你的问题,请参考以下文章

如何动态命名和创建子对象属性?

和创科技登陆新三板估值40亿 会成为企业SaaS下一个独角兽吗?

在 Django rest framework 中,在使用自定义模型时,我需要给 AUTH_USER_MODEL 啥值?

Scala之Future

每次调用fork()函数之后,父线程和创建出的子线程都是从fork()后开始执行

安装oracle数据库过程中sid指的是啥