user7693832
user7693832

Reputation: 6849

"Got KeyError when attempting to get a value for field `username` on serializer `UserCreateSerializer`

I have a user register APIView.

view:

class UserCreateAPIView(CreateAPIView):
    serializer_class = UserCreateSerializer
    permission_classes = [AllowAny]
    queryset = User.objects.all()

serializer:

class UserCreateSerializer(ModelSerializer):
    """
    User register
    """
    class Meta:
        model = User
        fields = [
            'username',
            'wechat_num',
            'password',
        ]
        extra_kwargs = {
            "password":{"write_only":True}
        }

    def create(self, validated_data):
        username=validated_data.pop('username')
        wechat_num = validated_data.pop('wechat_num')
        password=validated_data.pop('password')

        user_obj = User(
            username=username,
            wechat_num=wechat_num,
        )
        user_obj.set_password(password)
        user_obj.save()
        group=getOrCreateGroupByName(USER_GROUP_CHOICES.User)
        user_obj.groups.add(group)

        return validated_data

when I access this APIView, I will get the error:

KeyError at /api/users/register/ "Got KeyError when attempting to get a value for field username on serializer UserCreateSerializer.\nThe serializer field might be named incorrectly and not match any attribute or key on the dict instance.\nOriginal exception text was: 'username'."

but the database it will create the user success.

all test success:

enter image description here

Upvotes: 4

Views: 14779

Answers (3)

lodey
lodey

Reputation: 304

After defining your class you have to define those field, that what i did and it worked fine.

class UserCreateSerializer(ModelSerializer):
   username = serializer.CharField(max_length=<value>)

like this way you have to do. In mine i had same error. and i forgot to define password.

Upvotes: 0

von Oak
von Oak

Reputation: 833

From the method

def create(self, validated_data):

you should return the created instance. In your case, it should be

return user_obj

Upvotes: 1

Alasdair
Alasdair

Reputation: 308939

You are popping all of the fields from validated_data, so they won't be in the dictionary when you finally return it.

username=validated_data.pop('username')
wechat_num = validated_data.pop('wechat_num')
password=validated_data.pop('password')
...

return validated_data

Perhaps you want to change it to:

username=validated_data['username']
wechat_num = validated_data['wechat_num']
password=validated_data.pop('password')
...
return validated_data

Upvotes: 6

Related Questions