如何自定义TokenObtainPairSerializer字段,仅保留phone_number为必填项
自定义TokenObtainPairSerializer仅保留phone_number为唯一必填字段
默认情况下,TokenObtainPairSerializer会要求传入username和password两个必填字段,路由配置如下:
urlpatterns = [ path('api/token/', TokenObtainPairView.as_view()) ]
未填写时会返回必填字段提示:
{ "username": [ "This field is required." ], "password": [ "This field is required." ] }
如果想要仅用phone_number作为唯一必填字段,直接添加该字段到自定义序列化器里是不够的——父类的username和password依然会被标记为必填。解决方法需要两步:显式覆盖父类字段并设为非必填,同时重写验证逻辑以适配phone_number。
完整实现代码
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer from rest_framework import serializers from django.contrib.auth import get_user_model User = get_user_model() class MyTokenObtainPairSerializer(TokenObtainPairSerializer): # 覆盖父类的username和password,标记为非必填 username = serializers.CharField(required=False) password = serializers.CharField(required=False, write_only=True) # 定义必填的phone_number字段 phone_number = serializers.CharField(max_length=10, required=True) def validate(self, attrs): # 提取并校验phone_number phone_number = attrs.get('phone_number') if not phone_number: raise serializers.ValidationError({"phone_number": ["该字段为必填项"]}) # 根据手机号查找用户(需确保User模型中phone_number字段唯一) try: user = User.objects.get(phone_number=phone_number) except User.DoesNotExist: raise serializers.ValidationError({"phone_number": ["该手机号未注册"]}) # 将用户对象传入attrs,供父类生成token使用 attrs['user'] = user # 调用父类方法生成token数据 data = super().validate(attrs) # 可在此处添加额外响应字段(如用户昵称、权限等) return data class MyTokenObtainPairView(TokenObtainPairView): serializer_class = MyTokenObtainPairSerializer
关键说明
- 覆盖父类字段:通过显式定义
username和password并设置required=False,可以移除它们的必填要求。 - 重写validate方法:父类原有的验证逻辑依赖
username和password,因此需要替换为基于phone_number的用户查找逻辑,确保能正确获取用户对象以生成JWT Token。 - 用户模型要求:你的
User模型必须包含phone_number字段,且建议设置为唯一约束,避免查找用户时出现多条匹配的情况。
如果你的场景是短信验证码登录,还可以在validate方法中添加验证码校验逻辑(比如对比传入的code和缓存中的验证码),验证通过后再继续生成Token。
内容的提问来源于stack exchange,提问作者meg hidey
相关产品推荐
相关产品推荐

