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

如何在Django Rest Framework中为继承User模型的Player添加Token?

为Player模型创建并关联Token的正确解决方法

我来帮你解决这个问题,先拆解下错误根源,再给出两种可行的解决方案。

错误原因解析

你遇到的TypeError: Direct assignment to the forward side of a many-to-many set is prohibited. Use groups.set() instead.,核心问题出在**调用Player.objects.create_user(**validated_data)**这一步。

create_user是Django AbstractUser自带的UserManager提供的方法,但你的Player作为自定义MyUser的子类,默认使用的是普通的models.Manager,它没有处理groups、user_permissions这类多对多字段的逻辑,直接调用create_user就会触发多对多字段的赋值错误。

另外补充说明:Django REST Framework的Token模型是关联到你配置的AUTH_USER_MODEL(也就是你的MyUser)的,而Player是MyUser的单表继承子类,本质上属于MyUser实例,所以Token关联player是完全可行的,只是创建Player的方式需要调整。

方案一:手动处理密码哈希,直接创建Player

这种方法不需要修改模型结构,直接在Serializer里手动处理密码哈希,用create方法创建Player实例:

from django.contrib.auth.hashers import make_password
from rest_framework.authtoken.models import Token

class PlayerSerializer(serializers.ModelSerializer):
    class Meta:
        model = Player
        fields = '__all__'
        # 建议将password设为只写字段,避免接口返回明文密码
        extra_kwargs = {'password': {'write_only': True, 'required': True}}

    def create(self, validated_data):
        # 从验证数据中取出密码
        password = validated_data.pop('password')
        # 创建Player实例
        player = Player.objects.create(**validated_data)
        # 手动对密码进行哈希处理后保存
        player.password = make_password(password)
        player.save()
        # 为该Player创建并关联Token
        Token.objects.create(user=player)
        return player

方案二:为自定义用户模型添加管理器,复用create_user逻辑

如果你想沿用create_user的自动处理逻辑(它会自动哈希密码、设置默认用户状态等),可以给MyUser指定UserManager,让Player继承这个管理器:

首先修改你的模型代码:

from django.contrib.auth.models import AbstractUser, UserManager

class MyUserManager(UserManager):
    pass

class MyUser(AbstractUser):
    # 为自定义用户模型配置UserManager
    objects = MyUserManager()
    pass

class Player(MyUser):
    national_id = models.CharField(max_length=10)
    # 继承父类的UserManager
    objects = MyUserManager()

    def save(self, *args, **kwargs):
        self.username = self.email
        return super().save(*args, **kwargs)

然后更新Serializer代码:

from rest_framework.authtoken.models import Token

class PlayerSerializer(serializers.ModelSerializer):
    class Meta:
        model = Player
        fields = '__all__'
        extra_kwargs = {'password': {'write_only': True, 'required': True}}

    def create(self, validated_data):
        # 现在可以安全调用create_user方法
        player = Player.objects.create_user(**validated_data)
        # 创建关联的Token
        Token.objects.create(user=player)
        return player

这两种方案都能完美解决你的问题,第一种更直接快速,第二种更贴合Django用户模型的设计规范,你可以根据项目需求选择合适的方式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 14:22:32