database - register - Usuarios de Django y autenticación desde fuente externa.
register and login django (3)
En lugar de sobrescribir el método de save
, también puede desconectar la señal que lo invoca. Esto es lo que hago en algunas aplicaciones que tienen acceso de solo lectura a la base de datos de usuarios.
# models.py (for instance)
from django.contrib.auth.models import update_last_login, user_logged_in
user_logged_in.disconnect(update_last_login)
Tengo una aplicación Django que obtiene sus datos completamente de una fuente externa (consultada a través de HTTP). Es decir, no tengo la opción de una base de datos local. Los datos de la sesión se almacenan en la memoria caché (en mi servidor de desarrollo utilizo una base de datos SQLite, por lo que no es fuente de error) Estoy usando la vanguardia Django 1.1svn.
Ingrese el problema: quiero usar el propio sistema de autenticación de Django para los usuarios.
Parece bastante sencillo escribir mi propio Backend de autenticación, pero siempre con la condición de que tenga una base de datos local donde guardar a los usuarios. Sin base de datos mi principal problema es la persistencia.
Lo intenté con lo siguiente (suponiendo que datasource.get()
es una función que devuelve algún tipo de dict):
class ModelBackend (object):
"""Login backend."""
def authenticate (self, username=None, password=None):
"""Check, if a given user/password combination is valid"""
data = datasource.get (''login'', username, password)
if data and data[''ok'']:
return MyUser (username=username)
else:
raise TypeError
return None
def get_user (self, username):
"""get data about a specific user"""
try:
data = datasource.get (''userdata'', username)
if data and data[''ok'']:
return data.user
except:
pass
return None
class MyUser (User):
"""Django user who isn''t saved in DB"""
def save (self):
return None
Pero el método save()
intencionalmente perdido en MyUser parece romper el almacenamiento de sesión de un inicio de sesión.
¿Cómo debería ser MyUser
sin una base de datos local?
OK, es mucho más complicado de lo que pensaba. Primero, comience con docs.djangoproject.com/en/dev/howto/auth-remote-user , pero deberá ampliarlo con su propio servidor y backend.
from django.contrib.auth.backends import RemoteUserBackend
class MyRemoteUserBackend (RemoteUserBackend):
# Create a User object if not already in the database?
create_unknown_user = False
def get_user (self, user_id):
user = somehow_create_an_instance_of (MyUser, user_id)
return user
def authenticate (self, **credentials):
check_credentials ()
user = somehow_create_an_instance_of (MyUser, credentials)
return user
Entonces el usuario:
from django.contrib.auth.models import User
class MyUser (User):
def save (self):
"""saving to DB disabled"""
pass
objects = None # we cannot really use this w/o local DB
username = "" # and all the other properties likewise.
# They''re defined as model.CharField or similar,
# and we can''t allow that
def get_group_permissions (self):
"""If you don''t make your own permissions module,
the default also will use the DB. Throw it away"""
return [] # likewise with the other permission defs
def get_and_delete_messages (self):
"""Messages are stored in the DB. Darn!"""
return []
¡Uf! Django realmente no está diseñado para su uso sin una base de datos ...
grep
ping mostró que el único lugar al que se user.save()
(excepto para la creación de usuarios y el código de administración de contraseñas, que no necesita usar en absoluto) es django.contrib.auth.login()
, para actualizar el valor de user.last_login
.
# TODO: It would be nice to support different login methods, like signed cookies.
user.last_login = datetime.datetime.now()
user.save()
Si no desea que los datos del usuario descansen en la base de datos, intente agregar el método de save()
. Si tengo razón, debería funcionar.
def save(self, *args, **kwargs):
pass
Por supuesto, como no tiene ninguna persistencia en absoluto, debe considerar el almacenamiento en caché de los resultados de datasource.get
, de lo contrario, en el peor de los casos, puede terminar solicitando datos una y otra vez en cada acceso de usuario registrado.