Solución:
los request.user
está establecido por el django.contrib.auth.middleware.AuthenticationMiddleware
.
Cheque django/contrib/auth/middleware.py
:
class LazyUser(object):
def __get__(self, request, obj_type=None):
if not hasattr(request, '_cached_user'):
from django.contrib.auth import get_user
request._cached_user = get_user(request)
return request._cached_user
class AuthenticationMiddleware(object):
def process_request(self, request):
request.__class__.user = LazyUser()
return None
Entonces mira el get_user
funcionar en django/contrib/auth/__init__.py
:
def get_user(request):
from django.contrib.auth.models import AnonymousUser
try:
user_id = request.session[SESSION_KEY]
backend_path = request.session[BACKEND_SESSION_KEY]
backend = load_backend(backend_path)
user = backend.get_user(user_id) or AnonymousUser()
except KeyError:
user = AnonymousUser()
return user
Tu backend deberá implementar el get_user
función.
Yo también tengo un backend de autenticación personalizado y siempre tengo AnonymousUser
después exitoso autenticación e inicio de sesión. tuve el get_user
método en mi backend. Lo que me faltaba era eso get_user
debe obtener al usuario por pk
solo, no por correo electrónico o cualquiera que sea su credencial en authenticate
están:
class AccountAuthBackend(object):
@staticmethod
def authenticate(email=None, password=None):
try:
user = User.objects.get(email=email)
if user.check_password(password):
return user
except User.DoesNotExist:
return None
@staticmethod
def get_user(id_):
try:
return User.objects.get(pk=id_) # <-- tried to get by email here
except User.DoesNotExist:
return None
Es fácil pasar por alto esta línea en los documentos:
El método get_user toma un user_id, que podría ser un nombre de usuario, un ID de base de datos o lo que sea, pero tiene que ser la clave principal de su objeto Usuario, y devuelve un objeto Usuario.
Sucedió que email
no es la clave principal en mi esquema. Espero que esto le ahorre a alguien algo de tiempo.
Dice que ha escrito un backend de autenticación personalizado, pero de hecho lo que parece haber escrito es una aplicación de autenticación personalizada completa, que no interactúa con la de Django. contrib.auth
.
Si desea utilizar una base de datos no relacional para sus datos de autenticación, todo lo que necesita hacer es crear una clase que proporcione dos métodos: get_user(user_id)
y authenticate(**credentials)
. Consulte la documentación. Una vez que haya autenticado a un usuario, simplemente llame a los métodos de inicio de sesión normales de Django. No debería haber ninguna razón para configurar manualmente request.user
o poner algo en la sesión.
Actualizar después de editar Eso no tiene nada que ver con eso. No hay ningún requisito de que la clase de usuario se derive de auth.models.User
. Aún necesitas definir un get_user
método que devolverá una instancia de su clase de usuario.