如何通过TokenObtainPairSerializer修改simplejwt的username字段别名为phone
实现手机号登录接口字段重命名方案
问题根因
你之前的写法无法替换username字段的核心原因:TokenObtainPairSerializer并非依赖Meta.fields自动生成字段的常规ModelSerializer,它在类层面显式声明了username字段,子类通过Meta类配置字段列表,既不能移除父类显式声明的字段,也不能覆盖原有字段的对外暴露规则,因此才会出现接口同时显示username和phone两个入参字段的问题。
具体实现步骤
1. 编写自定义Token序列化器
直接移除父类自带的username声明,新增phone字段映射到模型的username属性,同时调整校验逻辑适配入参,完全复用simplejwt原生的密码校验、token生成能力,不需要重复实现校验逻辑:
from rest_framework import serializers from rest_framework_simplejwt.serializers import TokenObtainPairSerializer from django.contrib.auth.models import User class CustomTokenObtainPairSerializer(TokenObtainPairSerializer): # 移除父类显式声明的username字段 del TokenObtainPairSerializer._declared_fields['username'] # 定义对外暴露的入参字段 phone = serializers.CharField(max_length=20, write_only=True) password = serializers.CharField(max_length=65, min_length=8, write_only=True) def validate(self, attrs): # 将入参的phone值赋值给username,适配父类原生校验逻辑 attrs['username'] = attrs.get('phone') return super().validate(attrs)
2. 编写自定义登录视图
替换默认视图绑定的序列化器为我们自定义的版本:
from rest_framework_simplejwt.views import TokenObtainPairView from .serializers import CustomTokenObtainPairSerializer class CustomTokenObtainPairView(TokenObtainPairView): serializer_class = CustomTokenObtainPairSerializer
3. 更新路由配置
将原路由中指向默认TokenObtainPairView的条目替换为自定义视图,其他路由(注册、发OTP、校验OTP、刷新token)保持原有逻辑不变:
from django.urls import path from rest_framework_simplejwt.views import TokenRefreshView from .views import ( RegisterView, SendOtpView, VerifyOtpView, CustomTokenObtainPairView ) urlpatterns = [ path('register', RegisterView.as_view()), path('otp/send', SendOtpView.as_view()), path('otp/verify', VerifyOtpView.as_view()), path('token/', CustomTokenObtainPairView.as_view(), name='token_obtain_pair'), path('token/refresh/', TokenRefreshView.as_view(), name='token_refresh'), ]
效果验证
修改完成后重启服务,再次访问/token/端点,接口入参将仅展示phone和password两个字段,不会再出现易混淆的username提示。原有token签发、密码校验、refresh token换发的逻辑完全不受影响,你当前将手机号存储在User模型username字段的设计不需要做任何调整。
内容的提问来源于stack exchange,提问作者sandeepsinghnegi
相关产品推荐
相关产品推荐

