简体   繁体   English

如何将令牌添加到扩展 Django Rest Framework 中的用户模型的模型中?

[英]How to add Token to a model that extends the User Model in Django Rest Framework?

I have the following to create a user and add a Token to it:我有以下内容来创建用户并向其添加令牌:

User = get_user_model()

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ('id', 'username', 'password', 'first_name', 'last_name', 'email') 
        extra_kwargs = {'passwords': {'write_only': True, 'required': True}}

    def create(self, validated_data):
        user = User.objects.create_user(**validated_data)
        token = Token.objects.create(user=user)
        return user

I would like to be able to do the same thing for a Player:我希望能够为玩家做同样的事情:

class PlayerSerializer(serializers.ModelSerializer):
    class Meta:
        model = Player
        fields = '__all__'

    def create(self, validated_data):
        # what to do here? How to create a new token for 'Player'?

I've tried this:我试过这个:

def create(self, validated_data):
    player = Player.objects.create_user(**validated_data)
    token = Token.objects.create(user=player)
    return player

But got this error: TypeError: Direct assignment to the forward side of a many-to-many set is prohibited. Use groups.set() instead.但是得到了这个错误: TypeError: Direct assignment to the forward side of a many-to-many set is prohibited. Use groups.set() instead. TypeError: Direct assignment to the forward side of a many-to-many set is prohibited. Use groups.set() instead.

The Player model extends the 'MyUser' model: Player 模型扩展了“MyUser”模型:

class MyUser(AbstractUser):
    pass

class Player(MyUser):
    national_id = models.CharField(max_length=10)
    
    def save(self, *args, **kwargs):
        self.username = self.email
        return super().save(*args, **kwargs)

I assume that you are using a payload similar to this:我假设您正在使用与此类似的有效负载:

{
    "username": "root",
    "password": "test",
    "first_name": "a",
    "last_name": "b",
    "email": "a@b.com",
    "national_id": "123",
}

Django's AbstractUser comes with several fields not included in this payload (eg. is_staff , is_superuser ), most of which come with either default arguments, or are allowed to be null. Django 的AbstractUser带有几个未包含在此有效负载中的字段(例如is_staffis_superuser ),其中大多数带有默认参数,或者允许为空。

Because you specified fields = '__all__' in your PlayerSerializer , your endpoint is expecting every field to be present in the payload, hence your error.因为您在PlayerSerializer指定了fields = '__all__' ,您的端点期望负载中存在每个字段,因此您的错误。

If you were using a traditional model setup (by that I mean no inheritance), you would have received a helpful error message telling you exactly what's missing.如果您使用的是传统模型设置(我的意思是没有继承),您会收到一条有用的错误消息,告诉您到底缺少什么。 I suspect the model inheritance aspect part of your code broke the serializer early, resulting in an unhelpful message.我怀疑您的代码的模型继承方面部分很早就破坏了序列化程序,从而产生了无用的消息。

Anyways, if my assumption is correct, you can fix this in 2 ways:无论如何,如果我的假设是正确的,您可以通过两种方式解决此问题:

  • include all of AbstractUser 's fields in your payload;在您的负载中包含AbstractUser所有字段; see the source code for a full list查看完整列表的源代码

  • modify your serializer's meta to specify the fields you want.修改序列化程序的元数据以指定所需的字段。

eg:例如:

class PlayerSerializer(serializers.ModelSerializer):
    class Meta:
        model = Player
        fields = (
            'username',
            'password',
            'first_name',
            'last_name',
            'email',
            'national_id',
        )

    def create(self, validated_data):
        player = Player.objects.create_user(**validated_data)
        token = Token.objects.create(user=player)
        return player

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM