ошибка при попытке расширить модель пользователя в django restframework - PullRequest
1 голос
/ 04 августа 2020

Я хотел бы расширить модель пользователя Django, используя OneToOneField в моем проекте Django api, но получаю странную ошибку. Я надеюсь, что кто-нибудь сможет мне помочь. Ниже мой код и сообщение об ошибке.

models.py:

  class Profile(models.Model):
    yearOfExperience = models.PositiveIntegerField(default=1)
    profession = models.CharField(max_length=250, blank=True, null=True)
    dp = models.URLField(blank=True, null=True)
    qualification = models.CharField(max_length=255, blank=True, null=True)
    phoneNumber = models.CharField(max_length=255, blank=True, null=True)


@receiver(post_save, sender=CustomUser)
def create_user_profile(sender, instance=None, created=False, **kwargs):
    if created:
        Profile.objects.create(user=instance)
    instance.profile.save()

сериализатор :

  class ProfileSerializer(serializers.ModelSerializer):
    id = serializers.IntegerField(source = 'pk', read_only = True)
    username = serializers.CharField(source = 'user.username', read_only = True)
    email = serializers.CharField(source = 'user.email', read_only=True)
    
    class Meta:
        model = Profile
        fields = ('id', 'email', 'username', 'yearOfExperience',
            'qualification', 'profession', 'phoneNumber' 
        )

    def create(self, validated_data, instance=None):
        if 'user' in validated_data:
            user_data = validated_data.pop('user')
        user = CustomUser.objects.create(**validated_data)
        profile = Profile.objects.update_or_create(user=user, **validated_data)
        return user

apiView:

class ProfileListView(generics.ListCreateAPIView):
    permission_classes = (IsAuthenticatedOrReadOnly,)
    queryset =  Profile.objects.all()
    serializer_class = ProfileSerializer

    def perform_create(self, serializer):
        serializer.save(user=self.request.user)

Сообщение об ошибке:

File "/home/olaneat/Desktop/filez/project/django/funzone/lib/python3.7/site-packages/django/db/models/base.py", line 500, in __init__
    raise TypeError("%s() got an unexpected keyword argument '%s'" % (cls.__name__, kwarg))
TypeError: CustomUser() got an unexpected keyword argument 'yearOfExperience'

1 Ответ

0 голосов
/ 05 августа 2020

Я считаю, что вам не хватает поля user one to one в модели вашего профиля, поэтому добавьте его туда

class Profile(models.Model):
    user = models.OneToOneField(CustomUser, on_delete=models.CASCADE)
    ...

Поскольку вы используете post_save для своего профиля, нет необходимости в .create в вашем сериализаторе. Итак, что-то вроде этого:

class ProfileSerializer(serializers.ModelSerializer):
    username = serializers.SerializerMethodField(read_only = True)
    email = serializers.SerializerMethodField(read_only=True)

    class Meta:
        model = Profile
        fields = ('id', 'email', 'username', 'yearOfExperience',
            'qualification', 'profession', 'phoneNumber' 
        )

    def get_username(self, obj):
        return obj.user.username

    def get_email(self, obj):
        return obj.user.email

теперь просто отправьте сообщение из представления API, и профиль будет создан.

Если, однако, вы хотите сохранить .create для возможности добавления новые пользователи из API профиля тогда, возможно, что-то вроде этого:

class ProfileSerializer(serializers.ModelSerializer):
    username = serializers.SerializerMethodField(read_only = True)
    email = serializers.SerializerMethodField(read_only=True)
    
    class Meta:
        model = Profile
        fields = ('id', 'email', 'username', 'yearOfExperience',
            'qualification', 'profession', 'phoneNumber' 
        )

    def create(self, validated_data, instance=None):
        if 'user' in validated_data:
            user = validated_data.pop('user')
        else:
            user = CustomUser.objects.create(**validated_data)
        profile, created_profile = Profile.objects.update_or_create(user=user, **validated_data)
        return profile

    def get_username(self, obj):
        return obj.user.username
    
    def get_email(self, obj):
        return obj.user.email
...