2

I have a custom user in a Django 1.5 project, which uses the email field as the username:

class MyUser(AbstractUser): my_custom_field = models.CharField(max_length=20, blank=True, null=True) USERNAME_FIELD = 'email' MyUser._meta.get_field_by_name('email')[0]._unique = True MyUser.REQUIRED_FIELDS.remove('email') 

If I try to authenticate that user like so:

auth_user = authenticate(username=email, password=password) login(request, auth_user) 

I get this:

Traceback: File "/Users/user/dev/proj/app/core/views.py" in post 39. login(request, auth_user) File "/Users/user/.virtualenvs/proj/lib/python2.7/site-packages/django/contrib/auth/__init__.py" in login 92. request.session[BACKEND_SESSION_KEY] = user.backend File "/Users/user/.virtualenvs/proj/lib/python2.7/site-packages/django/utils/functional.py" in inner 203. return func(self._wrapped, *args) Exception Type: AttributeError at /signup Exception Value: 'AnonymousUser' object has no attribute 'backend' 

How am I supposed to authenticate a custom user?

5
  • What I meant was this AUTHENTICATION_BACKENDS = ( 'django.contrib.auth.backends.ModelBackend') Commented May 22, 2013 at 10:11
  • Did you set AUTH_USER_MODEL? Commented May 22, 2013 at 10:13
  • authenticate doesn't seem to be returning an actual User. Is it the standard method from django.contrib.auth? Are you sure email and password are correct? Commented May 22, 2013 at 10:14
  • Yes, I have AUTH_USER_MODEL set to appname.MyUser and from django.contrib.auth import authenticate, login, email and password are correct since I just created the user earlier in that flow Commented May 22, 2013 at 10:45
  • Looks like something about my custom user implementation is wrong. Do I need to override create_user() for MyUser? Commented May 22, 2013 at 10:58

2 Answers 2

4

My custom model didn't implement create_user() in its apparently-required custom manager.

Here's the full working code:

from django.contrib.auth.models import AbstractUser, BaseUserManager class MyUserManager(BaseUserManager): def create_user(self, email, password=None): if not email: raise ValueError('Users must have an email address') user = self.model( email=MyUserManager.normalize_email(email), ) user.set_password(password) user.save(using=self._db) return user def create_superuser(self, email, password): user = self.create_user(email, password=password, ) user.is_admin = True user.save(using=self._db) return user class MyUser(AbstractUser): some_custom_field = models.CharField(max_length=20, blank=True, null=True) objects = MyUserManager() USERNAME_FIELD = 'email' MyUser._meta.get_field_by_name('email')[0]._unique = True MyUser.REQUIRED_FIELDS.remove('email') 

Django 1.5 "custom user" implementation is an abomination.

Sign up to request clarification or add additional context in comments.

Comments

1

What Django documentation is saying is

If you’re entirely happy with Django’s User model and you just want to add some additional profile information, you can simply subclass django.contrib.auth.models.AbstractUser and add your custom profile fields

So the idea of AbstractUser is to use it only when you need to add a few additional fields to the user model without creating a separate db table like it was pre Django 1.5.

But when you need a different functionality (like using the email as username,which probably means you won't need the username field) the better approach is the extend the AbstractBaseUser class and set all the fields you need there. This way setting the USERNAME_FIELD='email' will work without writing custom create_user() method.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.