I want to use an email field as the username field for my custom user model. I have the following custom User model subclassing Django's AbstractUser model:
class CustomUser(AbstractUser): .... email = models.EmailField(max_length=255, unique=True) USERNAME_FIELD = 'email'
But when I run
python manage.py sql myapp
I get the following error:
FieldError: Local field 'email' in class 'CustomUser' clashes with field of similar name from base class 'AbstractUser'
The reason I include my own email field in the first place is to add the unique=True
option to it. otherwise I get:
myapp.customuser: The USERNAME_FIELD must be unique. Add unique=True to the field parameters.
Now, in respect to this: https://docs.djangoproject.com/en/1.5/topics/db/models/#field-name-hiding-is-not-permitted
How can I achieve this? (other then naming the field "user_email" or something like that instead)
If you want to use django's default authentication backend you cannot make username non unique. You will have to implement a class with get_user(user_id) and authenticate(request, **credentials) methods for a custom backend.
For Django's default user model, the user identifier is the username, for custom user models it is the field specified by USERNAME_FIELD (see Customizing Users and authentication). It also handles the default permissions model as defined for User and PermissionsMixin .
It's highly recommended to set up a custom User model when starting a new Django project. Without it, you will need to create another model (like UserProfile ) and link it to the Django User model with a OneToOneField if you want to add new fields to the User model.
Ian, thank you very much for the clever response :)
However, I've already "patched" me a solution.
Since AbstractUser
also have a username
field which is totaly unnecessary for me
I decided to create my "own" AbstractUser
.
By subclassing AbstractBaseUser
and PermissionsMixin
I retain most of the User model built-in methods without adding any code.
I also took advantage of that opportunity to create a custom Manager
to eliminate the use in username
field all together:
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin, BaseUserManager class CustomUser(AbstractBaseUser, PermissionsMixin): .... email = models.EmailField(max_length=255, unique=True) first_name = ... last_name = ... is_active = ... is_staff = ... .... objects = CustomUserManager() USERNAME_FIELD = 'email' class CustomUserManager(BaseUserManager): def create_user(self, email, password=None, **extra_fields): ..... def create_superuser(self, email, password, **extra_fields): .....
This solution does result in repetition of some of Django's built-in code (mainly model fields that already exist in AbstractUser
such as 'first_name', 'last_name' etc.) but also in a cleaner User object and database table.
It is a real shame that the flexibily introduced in 1.5 with USERNAME_FIELD
can not be used to actualy create a flexible User model under all existing constrains.
EDIT: There is a comprehensive worked example available in the official docs: https://docs.djangoproject.com/en/dev/topics/auth/customizing/#a-full-example
If your real target is unique "email" values, and ignoring "username" values, then you may:
sha256(user.email).hexdigest()[:30]
Add uniqueness this way:
class User(AbstractUser): class Meta: unique_together = ('email', )
This results in:
CREATE TABLE "myapp_user" ( ... "email" varchar(75) NOT NULL, UNIQUE ("email") )
works just as expected, and is pretty simple.
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