You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用ModelSerializer自定义TokenObtainPairSerializer认证字段?

使用djangorestframework-simplejwt实现注册登录合一端点,能否用ModelSerializer替代手动字段?

我正在使用djangorestframework-simplejwt,希望让TokenObtainPairView接收first_name、last_name、phone_number和email完成认证(替代默认的用户名密码),以此实现一个/register端点,单次请求完成注册与登录。

默认的TokenObtainPairView路由配置如下:

path('api/token/', TokenObtainPairView.as_view(), name='token_obtain_pair'),

我已经通过手动定义序列化器字段实现了功能,代码如下:

class MyTokenObtainPairSerializer(TokenObtainPairSerializer):
    
    first_name = serializers.CharField()
    last_name = serializers.CharField()
    email = serializers.EmailField()

class MyTokenObtainPairView(TokenObtainPairView):
    serializer_class = MyTokenObtainPairSerializer

现在想知道能不能改用ModelSerializer实现,比如下面这段无法正常运行的代码:

class MyTokenObtainPairSerializer(TokenObtainPairSerializer, ModelSerializer):
    
    class Meta:
        model = User
        fields = ['first_name', 'last_name', 'email']

可以实现,但需调整继承逻辑

直接多重继承TokenObtainPairSerializer和ModelSerializer会因为DRF序列化器的继承机制冲突导致失效,以下是两种可行的实现方案:

方案一:基于ModelSerializer集成Token生成逻辑

这种方案更贴合ModelSerializer的使用习惯,通过create方法完成用户创建与Token生成:

from rest_framework import serializers
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
from django.contrib.auth import get_user_model

User = get_user_model()

class RegisterLoginSerializer(serializers.ModelSerializer):
    access = serializers.CharField(read_only=True)
    refresh = serializers.CharField(read_only=True)

    class Meta:
        model = User
        fields = ['first_name', 'last_name', 'email', 'phone_number', 'password', 'access', 'refresh']
        extra_kwargs = {'password': {'write_only': True}}

    def create(self, validated_data):
        # 创建用户
        user = User.objects.create_user(
            email=validated_data['email'],
            first_name=validated_data['first_name'],
            last_name=validated_data['last_name'],
            phone_number=validated_data.get('phone_number'),
            password=validated_data['password']
        )
        # 生成JWT Token
        token_obj = TokenObtainPairSerializer.get_token(user)
        validated_data['access'] = str(token_obj.access_token)
        validated_data['refresh'] = str(token_obj)
        return validated_data

对应的视图使用CreateAPIView即可:

from rest_framework.generics import CreateAPIView

class RegisterLoginView(CreateAPIView):
    serializer_class = RegisterLoginSerializer

路由配置:

path('api/register/', RegisterLoginView.as_view(), name='register_login'),

方案二:基于TokenObtainPairSerializer自动拉取模型字段

如果想保留TokenObtainPairSerializer的核心逻辑,可以通过动态添加模型字段的方式实现:

from rest_framework import serializers
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
from django.contrib.auth import get_user_model

User = get_user_model()

class MyTokenObtainPairSerializer(TokenObtainPairSerializer):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # 自动从User模型添加所需字段
        required_fields = ['first_name', 'last_name', 'email', 'phone_number']
        for field_name in required_fields:
            model_field = User._meta.get_field(field_name)
            if field_name == 'email':
                self.fields[field_name] = serializers.EmailField(required=True)
            else:
                self.fields[field_name] = serializers.CharField(required=True)

    def validate(self, attrs):
        # 检查用户是否存在,不存在则创建
        try:
            user = User.objects.get(email=attrs['email'])
        except User.DoesNotExist:
            user = User.objects.create_user(
                email=attrs['email'],
                first_name=attrs['first_name'],
                last_name=attrs['last_name'],
                phone_number=attrs.get('phone_number'),
                password=attrs['password']
            )
        # 补全父类需要的username字段(默认认证逻辑依赖)
        attrs['username'] = user.username
        # 调用父类逻辑生成Token
        return super().validate(attrs)

视图保持原配置即可:

class MyTokenObtainPairView(TokenObtainPairView):
    serializer_class = MyTokenObtainPairSerializer

关键注意事项

  • 禁止直接多重继承TokenObtainPairSerializer和ModelSerializer,两者的初始化、验证逻辑会发生冲突。
  • 两种方案都必须同时处理用户创建和Token生成两个核心步骤。
  • 确保phone_number字段已在你的自定义User模型中定义。

内容的提问来源于stack exchange,提问作者meg hidey

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 07:20:42