Rok
Rok

Reputation: 1500

Django 1.6 AbstractUser not working

Trying to create my custom user model, this is the code I have:

models.py

class CustomUser(AbstractUser):
    USERNAME_FIELD = 'email'

CustomUser._meta.get_field_by_name('email')[0]._unique=True

settings.py

AUTH_USER_MODEL = 'myapp.CustomUser'

When doing the manage.py syncdb, the following error occurs:

CommandError: One or more models did not validate:
myapp.customuser: The field named as the USERNAME_FIELD should not be included in REQUIRED_FIELDS on a swappable User model.

Can anyone shed some light? Is there a better way of customizing the user model in Django 1.6 without rewriting the entire class extending AbstractBaseUser?

Btw, if I delete USERNAME_FIELD = 'email' from my code and change the core django auth/models.py >> AbstractUser definition, it works. I just can't seem to be able to override the USERNAME_FIELD...

Thanks!

Upvotes: 10

Views: 12170

Answers (4)

Shmuelt
Shmuelt

Reputation: 151

My solution was to set USERNAME_FIELD = "id". Hope that helps someone in the future.

Upvotes: 0

User
User

Reputation: 24731

Josvic hit the nail on the head but I want to provide the solution I used. It's pretty simple.

  1. Remove 'email' or whatever you're using are USERNAME_FIELD from REQUIRE_FIELDS.

  2. In the UserManager that you made, simply write:

    if not email: raise ValueError('Users must have an email address')

This way, you'll manually enforce that an email is required.

This solution is the one that is used here: https://docs.djangoproject.com/en/1.7/topics/auth/customizing/#a-full-example

Upvotes: 2

Rok
Rok

Reputation: 1500

Josvic, your solution partially resolved my issue. What I had to do in the end was this:

class CustomUser(AbstractUser):

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['username']

    def get_username(self):
        return self.email

CustomUser._meta.get_field_by_name('email')[0]._unique=True

This resolved the initial issue that REQUIRED_FIELDS cannot contain the USERNAME_FIELD and as I do not want to redefine the entire User and extend the AbstractBaseUser, I had to include the 'username' in the REQUIRED_FIELD as otherwise the syncdb fails for a different reason (expecting the username for the sake of saving it into the db):

self.UserModel._default_manager.db_manager(database).create_superuser(**user_data)
TypeError: create_superuser() takes exactly 4 arguments (3 given)

Consequently, when doing the syncdb for the first time and having to enter a superuser, the email must be entered twice, as an email as well as a username. It's awkward but it's the cleanest one that I can live with it.

Cheers!

Upvotes: 8

Joseph Victor Zammit
Joseph Victor Zammit

Reputation: 15310

As made clear by the error message, the reason for is that AbstractUser defines REQUIRED_FIELDS = ['email']. And you cannot set a field in the REQUIRED_FIELDS to be your USERNAME_FIELD. Further detail here.

So if you want email as your primary field the way forward is to extend and redefine the field email on AbstractBaseUser rather than on AbstractUser.

Also this question/answer pair might be relevant to you in case I did not fully grasp your requirements.

Upvotes: 12

Related Questions