Home > Blockchain >  How to change DRF endpoints's required fields
How to change DRF endpoints's required fields

Time:07-12

I am using jwt.io on my DRF project. As you know jwt.io has already a Login API view called 'TokenObtainPairView' and it requires 2 fields: username and password. But in our project, we want users to log in with their email instead of their username. I handle this with the following code:

class LoginAPIView(TokenObtainPairView):

def post(self, request, *args, **kwargs):
    email=request.data['email']
    request.POST._mutable = True
    profile=ProfileModel.objects.get(email=email)
    request.data['username']=profile.username
    request.POST._mutable = False
    return super().post(request, *args, **kwargs)

It works but on my swagger when front-end devs check the endpoint they see that the endpoint requires 2 fields: username and password. But I want them to see required fields such as email and password. here is the how my endpoint look like

Is there any way to change its required fields?

CodePudding user response:

I think if you don't need the username you can define your own user model like this.

The USERNAME_FIELD = 'email' on user model says to Django that use the email as username.

Don't forget change settings.py to use your own user model adding this const: AUTH_USER_MODEL = 'users.User' where users is the app name and User is the model name.

from django.contrib.auth.models import (
    AbstractBaseUser,
    BaseUserManager,
    PermissionsMixin
)


class UserManager(BaseUserManager):

    def create_user(self, email, password=None, **extra_fields):
    """Creates and saves a new user"""
        if not email:
            raise ValueError('Users must have an email address')
        user = self.model(email=self.normalize_email(email), **extra_fields)
        user.set_password(password)
        user.save(using=self._db)

        return user

    def create_superuser(self, email, password):
        if not email:
            raise ValueError('Users must have an email address')
        if not password:
            raise ValueError('Users must have a password')

        """Creates and saves a new super user"""
        user = self.create_user(email, password)
        user.is_staff = True
        user.is_superuser = True
        user.save(using=self._db)

        return user

class User(AbstractBaseUser, PermissionsMixin):
"""Custom user model that suppors using email instead of username"""

    email = models.EmailField(max_length=255, unique=True)
    is_active = models.BooleanField(default=True)
    is_staff = models.BooleanField(default=False)
    first_name = models.CharField(max_length=100)
    last_name = models.CharField(max_length=100)

    objects = UserManager()

    USERNAME_FIELD = 'email'

CodePudding user response:

By default TokenObtainPairSerializer uses the default username field defined by the model, but in case you need to change the behavior without changing the model you can override the token serializer to use the preferred field, i.e.:

from rest_framework_simplejwt.serializers import TokenObtainPairSerializer


class CustomTokenObtainPairSerializer(TokenObtainPairSerializer):
    username_field = 'email'


class LoginAPIView(TokenObtainPairView):
    _serializer_class = CustomTokenObtainPairSerializer
  • Related