【问题标题】:Manager isn't available; User has been swapped for 'pet.Person'经理不可用;用户已被替换为“pet.Person”
【发布时间】:2013-07-26 06:44:28
【问题描述】:

我在 django 中使用默认用户模型已经有一段时间了,我意识到,如果我需要进一步增强它,我必须在 django 1.5 中创建自己的自定义用户模型。

我创建了我的自定义用户模型,并且我有一个允许用户登录的功能。 我认为我的自定义用户模型与我的功能不兼容,因为它不允许我执行 request.user 。我该如何解决这个问题,以便我可以再次使用 request.user?

观看次数

 def LoginRequest(request):
         form = LoginForm(request.POST or None)    
    if request.user.is_authenticated():
             username = User.objects.get(username=request.user)
             url = reverse('world:Profile', kwargs = {'slug': person.slug})
             return HttpResponseRedirect(url)       
         if request.POST and form.is_valid():

             user = form.authenticate_user()
             login(request, user)
            username= User.objects.get(username=request.user)
                person = Person.objects.get(user=request.user)
            url = reverse('world:Profile', kwargs = {'slug': person.slug})
             return HttpResponseRedirect(url)

    return render(request, 'login.html',{'form': form})

型号

 class PersonManager(BaseUserManager):
     def create_user(self, email,date_of_birth, username,password=None,):
         if not email:
             msg = 'Users must have an email address'
             raise ValueError(msg)

         if not username:
              msg = 'This username is not valid'
        raise ValueError(msg)

         if not date_of_birth:
             msg = 'Please Verify Your DOB'
             raise ValueError(msg)

         user = self.model(

 email=PersonManager.normalize_email(email),username=username,date_of_birth=date_of_birth)

         user.set_password(password)
         user.save(using=self._db)
         return user

     def create_superuser(self,email,username,password,date_of_birth):
         user = self.create_user(email,password=password,username=username,date_of_birth=date_of_birth)
         user.is_admin = True
         user.is_staff = True
         user.is_superuser = True
         user.save(using=self._db)
         return user


 class Person(AbstractBaseUser, PermissionsMixin):

     email = models.EmailField(verbose_name='email address',max_length=255,unique=True,db_index=True,)
     username = models.CharField(max_length=255, unique=True)
     date_of_birth = models.DateField()

     USERNAME_FIELD = 'email'
     REQUIRED_FIELDS = ['username', 'date_of_birth',]

     is_active = models.BooleanField(default=True)
     is_admin = models.BooleanField(default=False)
     is_staff = models.BooleanField(default=False)

     objects = PersonManager()

     def get_full_name(self):
         return self.email

     def get_short_name(self):
         return self.email

     def __unicode__(self):
         return self.email

【问题讨论】:

    标签: django


    【解决方案1】:

    问题是User 指的是django.contrib.auth.models.User,现在你有一个Custom User pet.Person 假设你有settings.py

    AUTH_USER_MODEL = "pet.Person"
    

    您必须使用Custom User 模型定义User,您可以在使用User 的文件顶部使用get_user_model 来执行此操作

    from django.contrib.auth import get_user_model
    User = get_user_model()
    

    现在您可以使用Custom User 模型并且问题已得到修复。

    【讨论】:

    • 你好,这看起来可以解决我的问题 - 我想知道代码应该放在哪个文件中?谢谢!
    • @GershomMaes AUTH_USER_MODEL 在 settings.py 和您视图中的其他代码或您使用用户模型的任何地方,不客气:D
    • 工作,非常感谢!
    • 如果您在文档中查找此信息:docs.djangoproject.com/en/2.2/topics/auth/customizing/…
    • 可能这与这个问题无关,我只想注意相同的错误消息。在我的 Django 3.0.4 中,我使用了 .UserChangeForm 的 contrib.auth.forms.UserCreationForm 并且它们都在其 Meta 类中硬编码了 model=User(而不是在此文件中等于 get_user_model() 的 =UserModel)。我做了 PR 但我不知道替换 User->UserModel 是否正确并且 Django 项目中有很多 PR 等待。
    【解决方案2】:

    对于可能遇到此问题的其他人,我也通过简单地在 forms.py 上执行此操作来解决它:

    将其添加到 forms.py 文件的顶部

    from .models import YourCustomUser
    

    然后将其添加到您的forms.py CustomUser 表单中:

    class SignUpForm(UserCreationForm):
    #profile_year        = blaaa blaa blaaa irrelevant.. You have your own stuff here don't worry about it
    
       # here is the important part.. add a class Meta-
       class Meta:
          model = YourCustomUser #this is the "YourCustomUser" that you imported at the top of the file  
          fields = ('username', 'password1', 'password2', #etc etc, other fields you want displayed on the form)
    

    注意事项

    1. 此代码适用于我的情况。我有一个注册用户的视图,我这里遇到了问题,我解决了,我还没有尝试过登录用户。

    2. include = ()部分是必填项,也可以加exclude = (),但必须要有一个

    【讨论】:

    • 警告docs 表明您应该使用settings.AUTH_USER_MODELget_user_model() 而不是这种方法。我不确定这是否只是一个约定,或者是否存在安全问题。
    【解决方案3】:

    更新上述解决方案的重要警告... 如果您遇到此类问题,您可能已经尝试了网络上的各种解决方案,告诉您将 AUTH_USER_MODEL = users.CustomUser 添加到 settings.py,然后将以下代码添加到 views.py forms.py 和任何其他文件致电User:

    from django.contrib.auth import get_user_model
    User = get_user_model()
    

    然后当你得到错误时你会挠头:

    Manager isn't available; 'auth.User' has been swapped for 'users.User'
    

    任何时候您的代码引用User,例如:

    User.objects.get()
    

    因为您知道您已经将 objects = UserManager() 放入自定义用户类中(UserManager 是扩展 BaseUserManager 的自定义管理器的名称)。

    事实证明:

    User = get_user_model() # somewhere at the top of your .py file
    # followed by
    User.objects.get() # in a function/method of that same file
    

    不等于:

    get_user_model().objects.get() # without the need for User = get_user_model() anywhere
    

    也许不直观,但事实证明,在 python 中,在导入时执行一次 User = get_user_model() 不会导致在后续调用中定义 User(即它不会将 User 变成如果您来自 C/C++ 背景,您可能会期望这种“常量”;这意味着 User = get_user_model() 的执行发生在导入时,但随后在随后调用类或函数之前被取消引用/该文件中的方法)。

    综上所述,在所有引用User类的文件中(例如调用函数或变量如User.objects.get()User.objects.all()User.DoesNotExist等...):

    # Add the following import line
    from django.contrib.auth import get_user_model
    
    # Replace all references to User with get_user_model() such as...
    user = get_user_model().objects.get(pk=uid)
    # instead of  user = User.objects.get(pk=uid)
    # or
    queryset = get_user_model().objects.all()
    # instead of queryset = User.objects.all()
    # etc...
    

    希望这可以帮助其他人节省一些时间...

    【讨论】:

      【解决方案4】:

      forms.py

      # change
      from django.contrib.auth.models import User
      
      # to
      from django.contrib.auth import get_user_model
      

      然后在顶部添加如下代码

      User = get_user_model()
      

      【讨论】:

        【解决方案5】:

        上面提供的所有解决方案都不适用于我的情况。如果您使用 Django 3.1 版,还有另一种解决方案:

        在 auth/forms 中,注释掉第 10 行并将第 104 和 153 行中的模型更改为您定义的模型。

        【讨论】:

          猜你喜欢
          • 2021-12-24
          • 2019-07-20
          • 2018-07-27
          • 2020-06-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-03-19
          • 2018-04-01
          相关资源
          最近更新 更多