Reputation: 770
WHAT I WANT To HAPPEN I am using Django rest auth, 1) I want the users to be able to signup/register asking for their Email, username, and password. 2) When the user wants to log in, the email is what will be asked.
WHAT TO NOTE 1) The email is important to me because it will be verified to know is the user is real 2) The Username is important to me because a unique username will be able to easily access the profile of the user with style, for example, www.website.com/. I want to be able to do stuff like that with the username that is why it is important
WHAT IS HAPPENING 1) I noticed I cannot use both email and username at the same time, or rather I do not know how to set the Authentication backend up effectively
MY CODE
settings.py
INSTALLED_APPS = [
...
'rest_framework',
'rest_framework.authtoken',
'rest_auth',
'rest_auth.registration',
'allauth',
'allauth.account',
...
'accounts',
]
ACCOUNT_USER_MODEL_USERNAME_FIELD = None
ACCOUNT_EMAIL_REQUIRED = True
ACCOUNT_USERNAME_REQUIRED = False
ACCOUNT_AUTHENTICATION_METHOD = 'email'
ACCOUNT_USER_EMAIL_FIELD = 'email'
ACCOUNT_UNIQUE_EMAIL = True
ACCOUNT_LOGOUT_ON_GET = True
models.py
class UserManager(BaseUserManager):
"""
The User Manager
"""
def _create_user(self, email, fullname, password, is_staff, is_superuser, **extra_fields):
if not email:
raise ValueError('Users must have an email address')
now = timezone.now()
email = self.normalize_email(email)
fullname = fullname
user = self.model(
email=email,
fullname=fullname,
is_staff=is_staff,
is_active=True,
is_superuser=is_superuser,
last_login=now,
date_joined=now,
**extra_fields
)
user.set_password(password)
user.save(using=self._db)
return user
def create_user(self, email, fullname, password, **extra_fields):
return self._create_user(email, fullname, password, False, False, **extra_fields)
def create_superuser(self, email, fullname, password, **extra_fields):
user = self._create_user(email, fullname, password, True, True, **extra_fields)
user.save(using=self._db)
return user
class User(AbstractBaseUser, PermissionsMixin):
username = None
email = models.EmailField(max_length=254, unique=True)
fullname = models.CharField(max_length=250)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
last_login = models.DateTimeField(null=True, blank=True)
date_joined = models.DateTimeField(auto_now_add=True)
slug = models.SlugField(max_length=255, unique=True, blank=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['fullname']
objects = UserManager()
def __str__(self):
return self.email
I set the username to none because it doesn't work when I set it otherwise
serializer
class CustomRegisterSerializer(RegisterSerializer):
'''
a custom serializer that overides the default rest-auth, and for
the user to register himself
'''
username = None
email = serializers.EmailField(required=True)
password1 = serializers.CharField(write_only=True)
fullname = serializers.CharField(required=True)
slug = serializers.SlugField(read_only=True)
def get_cleaned_data(self):
super(CustomRegisterSerializer, self).get_cleaned_data()
return {
'password1': self.validated_data.get('password1', ''),
'email': self.validated_data.get('email', ''),
'fullname': self.validated_data.get('fullname', ''),
}
view
class CustomRegisterView(RegisterView):
'''
a custom register view that overrides the rest-auth's default
'''
permission_classes = [AllowAny]
queryset = User.objects.all()
please, this has been taking me a long time to fix, and I would appreciate it if someone can help me out. thank you
Upvotes: 1
Views: 2029
Reputation: 1274
To solve exactly the problems you are pointing, an alternative solution is django-graphql-auth. It does not affect django-rest-framework, both can be used together.
I want the users to be able to signup/register asking for their Email, username, and password.
Registration is made by providing email
, username
, password1
and password2
. But you can add more fields or change these on settings.
When the user wants to log in, the email is what will be asked.
Users can use email
or username
to login. But again, you can change it in settings and let only the email if you want.
The email is important to me because it will be verified to know is the user is real.
It does have the verification email flow, also have a secondary email verification.
I noticed I cannot use both email and username at the same time
In django-graphql-auth you can.
After installation and following the setup guide, you can make a simple flow like this example.
The registration is made by simple sending a graphql mutation like this (if you don't know what is or how to use graphql, the quickstart guide teaches you):
mutation {
register(
email:"[email protected]",
username:"user_username",
password1: "somerandompassword",
password2:"somerandompassword"
) {
success,
errors,
token,
refreshToken
}
}
Then, a model UserStatus
is created, related to your user model:
from django.contrib.auth import get_user_model
u = get_user_model().objects.get(username="user_username")
# check the user status
u.verified # False
u.archived # False
u.secondary_email # ""
During the registration, an email was sent to the user, with a link containing the token.
On you front end, you can use the token from the url to send other mutation:
mutation {
verifyAccount(
token:"<TOKEN HERE>",
) {
success, errors
}
}
After a successful verification, the status of your user now is:
u.verified # True
Here is a demo video from this flow:
(I'm the author.)
Upvotes: 1