django.contrib.auth.login 不会让用户登录

问题描述

我创建了一个自定义的 User 模型,如下所示:

class User(AbstractBaseUser):

    class Types(models.TextChoices):
        CUSTOMER = 'CUSTOMER','Customer'
        supplier = 'supplier','supplier'
        OPERATOR = 'OPERATOR','Operator'

    base_type = Types.CUSTOMER

    objects = UserManager()

    phone = models.IntegerField(unique=True)
    code = models.IntegerField(blank=True,null=True)
    type = models.CharField(max_length=20,choices=Types.choices,default=base_type)
    date_joined = models.DateTimeField(auto_Now_add=True)
    is_active = models.BooleanField(default=True)
    is_admin = models.BooleanField(default=False)

    USERNAME_FIELD = 'phone'
    required_FIELDS = []

    class Meta:
        verbose_name = 'user'
        verbose_name_plural = 'users'

    def __str__(self):
        return str(self.phone)

    def has_perm(self,perm,obj=None):
        return True

    def has_module_perms(self,app_label):
        return True

    @property
    def is_staff(self):
        return self.is_admin

以及 User 模型的经理:

class UserManager(BaseUserManager):
    def create_user(self,phone,code=663322,password=None):
        if not phone:
            raise ValueError('Users must have a phone number')
        user = self.model(
            phone=phone,code=code,)
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_superuser(self,password=None):
        user = self.create_user(
            phone=phone,password=password,)
        user.is_admin = True
        user.save(using=self._db)
        return user

我希望拥有 3 种不同的用户类型(客户、供应商、运营商),因此我创建了 3 个配置文件模型,并为每个配置文件模型的基本用户模型设置了一个 OnetoOneField(具有一些与用户类型相关的特定字段)。 我还创建了 3 个代理模型,如下所示:

class Customer(User):
    objects = CustomerManager()
    base_type = User.Types.CUSTOMER

    class Meta:
        proxy = True

class supplier(User):
    objects = supplierManager()
    base_type = User.Types.supplier

    class Meta:
       proxy = True

class Operator(User):
    objects = OperatorManager()
    base_type = User.Types.OPERATOR

    class Meta:
        proxy = True

他们的经理都是这样的(只有get_queryset方法不同):

class supplierManager(models.Manager):
    def create(self,code=223322,password=None):
        if not phone:
            raise ValueError('Users must have a phone number')

        user = self.model(
            phone=phone,type='supplier',)
        user.set_password(password)
        user.save(using=self._db)
        return user

    def get_queryset(self,*args,**kwargs):
        return super().get_queryset(*args,**kwargs).filter(type='supplier')

每种用户类型都有自己的注册方式,所以我制作了 3 个不同的身份验证后端(OperatorBackend 与其他两个相同):

class CustomerBackend(BaseBackend):
    def authenticate(self,request,phone=None,code=None):
        if phone and code:
            try:
                user = Customer.objects.get(phone=phone)
                if user.code == code:
                    return user
                return None
            except Customer.DoesNotExist:
                return None

    def get_user(self,user_id):
        try:
            return Customer.objects.get(pk=user_id)
        except Customer.DoesNotExist:
            return None


class supplierBackend(BaseBackend):
    def authenticate(self,first_name=None):
        if phone and first_name:
            try:
                user = supplier.objects.get(phone=phone)
                if user.sprofile.first_name == first_name:
                    return user
                return None
            except User.DoesNotExist:
                return None

    def get_user(self,user_id):
        try:
            supplier.objects.get(pk=user_id)
        except supplier.DoesNotExist:
            return None

以下是我对用户登录的看法(authenticate 是 django 的身份验证方法):

def customer_login(request):
    if request.method == 'POST':
        form = CustomerLoginForm(request.POST)
        if form.is_valid():
            cd = form.cleaned_data
            user = authenticate(request,phone=cd['phone'],code=cd['code'])
            if user is not None:
                login(request,user,backend='accounts.backends.CustomerBackend')
                messages.success(request,'Logged in','success')
                return redirect('accounts:home')
            else:
                messages.error(request,'User is None','danger')
    else:
        form = CustomerLoginForm()

    context = {
        'form': form,}
    return render(request,'accounts/customer_login.html',context)


def supplier_login(request):
    if request.method == 'POST':
        form = supplierLoginForm(request.POST)
        if form.is_valid():
            cd = form.cleaned_data
            user = authenticate(request,first_name=cd['first_name'])
            if user is not None:
                login(request,backend='accounts.backends.supplierBackend')
                messages.success(request,'danger')
    else:
        form = supplierLoginForm()

    context = {
        'form': form,'accounts/supplier_login.html',context)

我的问题是当我想使用 CUSTOMER 用户类型登录时,它可以工作并让用户登录。但是当我尝试使用其他用户类型登录时,它不起作用并且 request.user 返回 AnonymousUser . 我已经注册自定义身份验证后端(django 的认 ModelBackend 仍然存在)并且 settings.py 文件和身份验证后端中的 AUTH_USER_MODEL 似乎不是问题,因为它们在提供正确凭据时返回用户。我尝试从管理面板和通过经理创建新用户,但没有任何区别。也许我在这种实现上走错了方向,我还是编程新手。任何帮助表示赞赏。

编辑: 我尝试在登录后访问用户的 session_key 和后端,结果登录功能确实有效。但是 request.user.is_authenticated 在使用 supplierBackend 时由于某种原因返回 False。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)