I have a Django app that gets it's data completely from an external source (queried via HTTP). That is, I don't have the option for a local database. Session data is stored in the cache (on my development server I use a SQLite database, so that is no error source). I'm using bleeding edge Django 1.1svn.
Enter the problem: I want to use Django's own authentication system for the users.
It seems quite simple to write my own Authentication Backend, but always just under the condition that you have a local database where to save the users. Without database my main problem is persistence.
I tried it with the following (assume that datasource.get()
is a function that returns some kind of 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
But the intentionally missing save()
method on MyUser seems to break the session storage of a login.
How should MyUser
look like without a local database?
Add the above AuthenticationBackendAnonymous middleware into AUTHENTICATION_BACKENDS in your settings.py and use the snippet anonymous_or_real(request) in your views, which returns a user. Comment out the bit where it creates a profile if you are not using profiles.
For Django 1.10 + As Richard mentioned is_authenticated is a function, so in your view it should be called like: request. user. is_authenticated() . Because of django templating language there can be confusion, because calling this in a template makes it appear as a property and not a method.
OK, it's much more complicated than I thought. First, start with http://docs.djangoproject.com/en/dev/howto/auth-remote-user/, but you'll need to extend it with your own backend and user.
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
Then the user:
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 []
Phew! Django really isn't designed for usage without a database...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With