I am trying to write an API using django rest framework in which, you give a username and a password and in return you get an AuthToken or in other words you login. now I want this API to also return some fields like the email of the user along with the AuthToken. so if the authentication was successful, the get an authToken and the user's email. Can anyone help me on how I could be able to do this by adding or changing a bit of my code?
These are my models:
class UserManager(BaseUserManager):
def createUser(self, email, password=None, **extra_fields):
if not email:
raise ValueError('Email Not Found!!!')
user = self.model(email=self.normalize_email(email), **extra_fields)
user.set_password(password)
user.save(using=self._db)
return user
def createSuperUser(self, email, password):
user = self.createUser(email, password)
user.isAdmin = True
user.isSuperUser = True
user.save(using=self._db)
return user
class User(AbstractBaseUser, PermissionsMixin):
username = models.CharField(max_length=100, unique=True, validators=[RegexValidator(regex="^(?=[a-z0-9._]{5,20}$)(?!.*[_.]{2})[^_.].*[^_.]$")])
email= models.EmailField(max_length=100, unique=True, validators=[EmailValidator()])
name = models.CharField(max_length=100)
isSuspended = models.BooleanField(default=False)
isAdmin = models.BooleanField(default=False)
emailActivation = models.BooleanField(default=False)
balance = models.IntegerField(default=0)
objects = UserManager()
USERNAME_FIELD = 'username'
These are my serializers:
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = get_user_model()
fields = ('username','email', 'password', 'name')
extra_kwargs = {'password': {'write_only': True, 'min_length': 8}}
def create(self, validated_data):
return get_user_model().objects.createUser(**validated_data)
def update(self, instance, validated_data):
password = validated_data.pop('password', None)
user = super().update(instance, validated_data)
if password:
user.set_password(password)
user.save()
return user
class AuthTokenSerializer(serializers.Serializer):
username = serializers.CharField()
password = serializers.CharField(trim_whitespace=False)
def validate(self, attrs):
username = attrs.get('username')
password = attrs.get('password')
user = authenticate(
request=self.context.get('request'),
username= username,
password= password
)
if not user:
msg = 'Authentication Failed.'
raise serializers.ValidationError(msg, code='authentication')
attrs['user'] = user
return attrs
And finally, these are my views:
class CreateUserView(generics.CreateAPIView):
serializer_class = UserSerializer
class CreateTokenView(ObtainAuthToken):
serializer_class = AuthTokenSerializer
renderer_classes = api_settings.DEFAULT_RENDERER_CLASSES
class ManageUserView(generics.RetrieveAPIView):
serializer_class = UserSerializer
authentication_classes = (authentication.TokenAuthentication,)
permission_classes = (permissions.IsAuthenticated,)
def get_object(self):
return self.request.user
create a new serializer inside serializer.py
from rest_framework.authtoken.models import Token as DefaultTokenModel
class TokenSerializer(serializers.ModelSerializer):
user = UserSerializer()
class Meta:
model = DefaultTokenModel
fields = ('key', 'user',)
add this function in views.py
def get_token_response(user):
serializer_class = TokenSerializer
token, _ = DefaultTokenModel.objects.get_or_create(user=user)
serializer = serializer_class(instance=token)
return Response(serializer.data, status=status.HTTP_200_OK)
now override post method of CreateTokenView
def post(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
user = serializer.validated_data['user']
return get_token_response(user)