Using custom User model in Django

Django’s auth module django.contrib.auth is created so that additional project specific data is appended to the User model by using OneToOneField in some other model pointing to the User model. I wanted to have MyUser accessible as request.user.

It is possible to create a middleware which replaces the user object after Django has populated it. This works, but it is wrong as the default User object has been used first and then replaced with something else.

This is the User model I would like to use:

class MyUser(models.Model):
  class Meta:
    proxy = True

It is an empty proxy for this example. The user object can be pretty much whatever you want.

Django’s auth module has a way to use different auth backends. All user object related operations are handled in the backend and we can change the backend. Sounds nice.

class MyAuthBackend(ModelBackend):
  def authenticate(**credentials):
    return super(MyAuthBackend, self).authenticate(**credentials)

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

This auth backend is then enabled in the settings.py file:

AUTHENTICATION_BACKENDS = (
  'myauth.MyAuthBackend',
  )

Now we’ve achieved the goal. Django’s auth system has populated request.user with our MyUser instance.

If you are creating reusable Django app then you should always remember to get the User object from django.contrib.auth.get_user(user_id) if you want to have access to other than the current user in request.user.

There are downsides in this. One of the biggest being that your user model should always be a proxy for the Djangos user model if you want to enable compatibility with other apps.