You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django自定义认证后端登录报错:缺少request参数求助

自定义认证后端登录报错:TypeError: authenticate()缺少request参数

登录时触发如下异常:

Internal Server Error: /login/
Traceback (most recent call last):
  File "C:\Users\G-FIVE\Desktop\Projects\revenue\venv\Lib\site-packages\django\core\handlers\exception.py", line 55, in inner
    response = get_response(request)
               ^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\G-FIVE\Desktop\Projects\revenue\venv\Lib\site-packages\django\core\handlers\base.py", line 197, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\Projects\revenue\authentication\views.py", line 12, in login
    usuario = UsuarioAuthBackend.authenticate(request, email=email, password=password)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: UsuarioAuthBackend.authenticate() missing 1 required positional argument: 'request'
[09/Jun/2023 10:47:15] "POST /login/ HTTP/1.1" 500 66119

自定义用户模型、认证后端、登录视图及配置均已设置,但系统提示缺少request参数,相关代码如下:

自定义用户模型

from django.db import models
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager

# choices
CALIFICACION_USUARIO_CHOICES = [
    (0,0),
    (1,1),
    (2,2),
    (3,3),
    (4,4)
]

# Create your models here.
class UsuarioManager(BaseUserManager):
    use_in_migrations = True

    def _create_user(self, email, password, **extra_fields):
        if not email:
            raise ValueError('El usuario debe tener un correo electrónico')
        
        email = self.normalize_email(email)
        usuario = self.model(email=email, **extra_fields)
        usuario.set_password(password)
        usuario.save(using=self._db)

        return usuario


    def create_user(self, email=None, password=None, **extra_fields):
        extra_fields.setdefault('is_staff', True)
        extra_fields.setdefault('is_superuser', False)
        return self._create_user(email, password, **extra_fields)
    
    def create_superuser(self, email, password, **extra_fields):
        extra_fields.setdefault('is_staff', True)
        extra_fields.setdefault('is_superuser', True)

        if extra_fields.get('is_staff') is not True:
            raise ValueError('Superusuario debe tener la propiedad "is_staff=True"')
        if extra_fields.get('is_superuser') is not True:
            raise ValueError('Superusuario debe tener la propiedad "is_superuser=True"')
        
        return self._create_user(email, password, **extra_fields)

class Usuario(AbstractBaseUser):
    first_name = models.CharField(verbose_name='Nombre', max_length=255)
    last_name = models.CharField(verbose_name='Apellidos', max_length=255, blank=True, null=True)
    email = models.EmailField(verbose_name='Correo', unique=True, max_length=255)
    cedula = models.CharField(verbose_name='Cédula de Identidad', null=False, blank=False, max_length=255)
    telefono = models.CharField(verbose_name='Teléfono', max_length=255, null=False, blank=False)
    calificacion = models.SmallIntegerField(verbose_name='Calificación', null=False, blank=False, choices=CALIFICACION_USUARIO_CHOICES, default=0)
    direccion = models.TextField(verbose_name='Dirección', null=True, blank=True)
    foto_perfil = models.ImageField(verbose_name='Foto de perfil', max_length=255, null=True, blank=True, upload_to='perfil/')
    terminos_y_condiciones = models.BooleanField(verbose_name='Términos y condiciones', default=False)
    is_active = models.BooleanField(verbose_name='active',default=True)
    is_staff = models.BooleanField(verbose_name='staff status', default=False)
    is_superuser = models.BooleanField(verbose_name='superuser status', default=False)

    objects = UsuarioManager()

    USERNAME_FIELD = 'email'

    def __str__(self):
        return f'{self.first_name} {self.last_name}'
    
    def has_perm(self,perm,obj=None):
        return True
    
    def has_module_perms(self,app_label):
        return True
    
    def get_email_user(self):
        return self.email.lower()
    
    def save(self, *args, **kwargs):
        self.email = self.email.lower()
        return super(Usuario, self).save(*args, **kwargs)
    
    class Meta:
        verbose_name = 'Usuario'
        verbose_name_plural = 'Usuarios'
        ordering = ['-id']

自定义认证后端

from django.contrib.auth.backends import ModelBackend
from authentication.models import Usuario

class UsuarioAuthBackend(ModelBackend):
     def authenticate(self, request, **kwargs):
          email = kwargs['email']
          password = kwargs['password']

          try:
               usuario = Usuario.objects.get(email=email)
               if usuario.check_password(password) is True:
                    return usuario
          except Usuario.DoesNotExist:
               return None

登录视图

from django.shortcuts import render, redirect
from django.contrib.auth import login, logout
from authentication.authentication import UsuarioAuthBackend
from authentication.forms import FormUsuario

# Create your views here.
def login(request):
    if request.method == 'POST':
        email = request.POST['email']
        password = request.POST['password']

        usuario = UsuarioAuthBackend.authenticate(request, email=email, password=password)

        if usuario is not None:
            login(request, usuario)
            return redirect('home')
        
    return render(request, 'login.html')

settings.py配置

AUTHENTICATION_BACKENDS = [
    'django.contrib.auth.backends.ModelBackend',
    'authentication.authentication.UsuarioAuthBackend'
]

解决方案

问题出在登录视图中直接调用了UsuarioAuthBackend.authenticate类方法,而authenticate是实例方法,需要先实例化类再调用,或者更规范的是使用Django内置的django.contrib.auth.authenticate函数,它会自动遍历你配置的认证后端进行验证。

方案一(推荐):使用Django内置authenticate函数

修改登录视图代码:

from django.shortcuts import render, redirect
from django.contrib.auth import login, logout, authenticate  # 导入authenticate
from authentication.forms import FormUsuario

def login(request):
    if request.method == 'POST':
        email = request.POST['email']
        password = request.POST['password']

        # 使用Django内置的authenticate函数,自动使用配置的后端验证
        usuario = authenticate(request, email=email, password=password)

        if usuario is not None:
            login(request, usuario)
            return redirect('home')
        
    return render(request, 'login.html')

方案二:手动实例化后端类

如果一定要手动调用自定义后端的方法,需要先实例化:

# 在视图中替换原来的调用代码
backend = UsuarioAuthBackend()
usuario = backend.authenticate(request, email=email, password=password)

推荐使用第一种方案,符合Django标准认证流程,能自动处理多后端验证逻辑。


内容的提问来源于stack exchange,提问作者Angel Daniel Ascanio Salazar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 08:12:05