首页 > 解决方案 > drf 不创建没有配置文件密钥的配置文件

问题描述

我正在尝试在创建用户时创建用户配置文件。我收到此错误:

profile_data = validated_data.pop('profile')
KeyError: 'profile'

当我在创建用户时没有传递配置文件密钥但我在 customuserSerializers 中提到不需要 userprofileserialzer。如果我不传递配置文件密钥,我只想保存 null 。

模型.py:

class CustomUser(AbstractBaseUser, PermissionsMixin):
    first_name = models.CharField(_('first name'), max_length=50)
    last_name = models.CharField(_("last name"), max_length=50)
    email = models.EmailField(_('email address'), unique=True)
    mobile_number = PhoneNumberField()
    is_staff = models.BooleanField(default=False)
    is_active = models.BooleanField(default=True)
    date_joined = models.DateTimeField(default=timezone.now)
    user_type = models.IntegerField(_("user_type"))
    otp = models.CharField(_("otp"), max_length=10, default="0")
    is_varified = models.BooleanField(default=False)
    USER_TYPE_CHOICES = (
        (1, 'users'),
        (2, 'courier'),
        (3, 'admin'),
    )

    user_type = models.PositiveSmallIntegerField(
        choices=USER_TYPE_CHOICES, null=True)

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = []

    objects = CustomUserMananager()

    def __str__(self):
        return self.email


class UserProfile(models.Model):
    user = models.OneToOneField(
        CustomUser, primary_key=True, related_name='userProfile', on_delete=models.CASCADE,)
    gender = models.CharField(max_length=10, blank=True, null=True)
    age = models.IntegerField(blank=True, null=True)
    image = models.ImageField(
        upload_to='api/user_profile/', blank=True, null=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def __unicode__(self):
        return self.user.first_name

序列化程序.py:

class UserProfileSerializer(serializers.ModelSerializer):
class Meta:
    model = UserProfile
    read_only_fields = ('created_at', 'updated_at',)
    exclude = ('user',)


class CustomUserSerializer(serializers.ModelSerializer):
    profile = UserProfileSerializer(required=False)
    password = serializers.CharField(write_only=True, required=False)

    class Meta:
        model = CustomUser
        fields = ('id', 'first_name', 'last_name', 'email',
                  'mobile_number', 'password', 'is_active', 'user_type', 'otp', 'profile')

    def create(self, validated_data):
        profile_data = validated_data.pop('profile')
        user = CustomUser.objects.create(**validated_data)
        UserProfile.objects.create(user=user, **profile_data)
        return user

    def update(self, instance, validated_data):
        profile_data = validated_data.pop('profile')
        # update user data
        instance.first_name = validated_data.get(
            'first_name', instance.first_name)
        instance.last_name = validated_data.get(
            'last_name', instance.last_name)
        instance.email = validated_data.get('email', instance.email)
        # update user profile
        if not instance.profile:
            UserProfile.objects.create(user=instance, **profile_data)
        instance.age = profile_data.get('age', instance.profile.age)
        instance.gender = profile_data.get('gender', instance.profile.gender)
        instance.save()
        password = validated_data.get('password', None)
        if password:
            instance.set_password(password)
            instance.save()
            update_session_auth_hash(self.context.get('request'), instance)

        return instance

视图.py:

    @api_view(["POST"])
    @permission_classes((AllowAny,))
    def register(request):
        #permission_classes = [(AllowAny, )]
        serializer = CustomUserSerializer(data=request.data)
        # print(serializer)
        if serializer.is_valid():
            serializer.is_active = False
           # serializer.make_password(request.data.get('password'))
            serializer.save()
            user_otp = randint(9999, 99999)
            otp_code = str(user_otp)
            email = request.data.get('email')
    
            send_mail(
                'Otp verification',
                otp_code,
                'chenaj

il.com',
            [email],
            fail_silently=False,
        )
        # serializer.save(otp=user_otp)
        otp_update = CustomUser.objects.get(email=request.data.get('email'))
        otp_update.otp = user_otp
        otp_update.save()
        user = CustomUser.objects.get(email=email)
        token, created = Token.objects.get_or_create(user=user)
        current_time = datetime.datetime.now()
        return Response({'status_code': status.HTTP_200_OK, 'status': 'true', 'currentTimeStamp': current_time, 'message': 'User registered successfully, OTP sent to your Mail', 'data': {'id': user.id, 'token': token.key, 'user_type': user.user_type}}, status=status.HTTP_200_OK)
    return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


    @api_view(["POST"])
    @permission_classes((IsAuthenticated, AllowAny))
    def verifyUserOtp(request):
        print("data.......////")
        serializers = VerifyUserOtpSerializer(data=request.data)
        if serializers.is_valid(raise_exception=True):
            token = request.data.get('email')
            otp = request.data.get('otp')
            if CustomUser.objects.filter(otp=otp).exists():
                user = CustomUser.objects.get(otp=otp)
                user.is_varified = 1
                user.save()
                token, created = Token.objects.get_or_create(user=user)
            print(user.profile.age)
            return Response({'status_code': status.HTTP_200_OK, 'status': 'true', 'currentTimeStamp': datetime.datetime.now(), 'data': {'id': user.id, 'first_name': user.first_name, 'last_name': user.last_name, 'email': user.email, 'token': token.key, 'user_type': user.user_type}}, status=status.HTTP_200_OK)
        return Response({'message': 'OTP not matched', 'status': 'false', 'status_code': status.HTTP_401_UNAUTHORIZED, 'currentTimeStamp': datetime.datetime.now()}, status=status.HTTP_400_BAD_REQUEST)

在这个 verifyuserotp 函数中,我无法使用 user.profile.age 访问配置文件对象。

标签: djangodjango-rest-framework

解决方案


为避免出现此错误,您需要为.pop方法提供默认值,例如None

并且只要返回值为None,就不要创建Profile记录。

def create(self, validated_data):
        profile_data = validated_data.pop('profile', None)
        user = CustomUser.objects.create(**validated_data)
        if profile_data:
            UserProfile.objects.create(user=user, **profile_data)
        return user

这应该可以解决您的问题。


推荐阅读