Search code examples
pythondjango-rest-frameworkdjango-allauthdjango-rest-auth

Best practice for email required in django-rest-auth


What is the best (easiest?) way to make it a requirement to have an email only for user registration and not make username a requirement in the django-rest-auth framework?

Would I need to write a new User Serializer, for example? Is there a flag setting that I can set True or False to turn off or on this requirement instead?

Thanks


Solution

  • You'll need to write your own AbstractUser and BaseUserManager classes. Fortunately it's pretty simple, add something like this to your app's models:

    from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
    from django.db import models
    
    class Account(AbstractBaseUser):
        email = models.EmailField(unique=True)
        username = models.CharField(max_length=40, unique=True, blank=True)
    
        first_name = models.CharField(max_length=40, blank=True)
        last_name = models.CharField(max_length=40, blank=True)
    
        is_admin = models.BooleanField(default=False)
    
        created_at = models.DateTimeField(auto_now_add=True)
        updated_at = models.DateTimeField(auto_now=True)
    
        objects = AccountManager()
    
        # This tells Django that this field is absolutely important...
        USERNAME_FIELD = 'email'
        # ...and username is now optional because it doesn't show up here!
        REQUIRED_FIELDS = []
    
        def __unicode__(self):
            return self.email
    
        def get_full_name(self):
            return ' '.join([self.first_name, self.last_name])
    
        def get_short_name(self):
            return self.first_name
    
    class AccountManager(BaseUserManager):
        def create_user(self, email, password=None):
            if not email:
                raise ValueError('User must provide an e-mail address')
    
            account = self.model(
                email=self.normalize_email(email)
            )
    
            account.set_password(password)
            account.save()
    
            return account
    
        def create_superuser(self, email, password=None):
            account = self.create_user(email, password)
    
            account.is_admin = True
            account.save()
    
            return account
    

    Next, tell Django that this model is your project's new User class. Add the following to your settings.py file:

    AUTH_USER_MODEL = 'apiapp.Account'
    

    Once that's done, just migrate:

    python manage.py makemigrations
    python manage.py migrate
    

    From that point on new users will be represented by this new model (you'd have to handle migrations manually), including anywhere you might use self.request.user!