DRF:未在ModelSerializer类中执行自定义更新方法

时间:2019-11-17 14:18:11

标签: django django-rest-framework

我正在使用Django Rest Framework编写REST API。我在这里令人费解。 我有一个名为“用户”的应用。

Models.py:

@python_2_unicode_compatible
class User(AbstractUser):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    profile_picture = models.ForeignKey(File, on_delete=models.DO_NOTHING, default=None, null=True, blank=True)
    email = models.EmailField('Email address', unique=True)
    name = models.CharField('Name', default='', max_length=255)
    phone_no = models.CharField('Phone Number', max_length=255, unique=True)
    company_name = models.CharField('Company Name', default='', max_length=255)
    verification_token = models.CharField('Verification Token', default='', max_length=255)
    address = models.CharField('Address', default='', max_length=255)
    address_coordinates = models.CharField('Address Coordinates', default='', max_length=255)
    country = models.CharField('Country', default='', max_length=255)
    pincode = models.CharField('Pincode', default='', max_length=255)
    pan_number = models.CharField('Pan Number', default='', max_length=255, blank=True)
    gst_number = models.CharField('GST Number', default='', max_length=255, blank=True)
    is_advertisor = models.BooleanField(default=False)
    is_signage_owner = models.BooleanField(default=False)
    phone_verified = models.BooleanField(default=False)
    email_verified = models.BooleanField(default=False)
    updated_at = models.DateTimeField(auto_now_add=True)
    from_time = models.TimeField(blank=True, default='00:00')
    to_time = models.TimeField(blank=True, default='00:00')
    category = models.CharField('Category', default='', max_length=255, blank=True)
    reset_token = models.CharField(max_length=255, default='')
    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['username']

    def __str__(self):
        return self.email

Views.py:

class UserViewSet(mixins.RetrieveModelMixin,
                  mixins.ListModelMixin,
                  mixins.UpdateModelMixin,
                  mixins.CreateModelMixin,
                  viewsets.GenericViewSet):
    queryset = User.objects.all()
    permission_classes = (AllowAny,)
    filter_backends = [DjangoFilterBackend]
    filterset_fields = ['id', 'email', 'phone_no']

    def get_serializer_class(self):
        if self.action == 'create':
            return CreateUserSerializer
        elif self.action == 'update':
            return UpdateUserSerializer
        else:
            return UserSerializer

Serializers.py:

class CreateUserSerializer(serializers.ModelSerializer):
    def create(self, validated_data):
        token = account_activation_token.make_token(validated_data['email'])
        validated_data['verification_token'] = token
        user = User.objects.create_user(**validated_data)
        subject = 'Account Verification'
        message = 'Your Verification token is http://167.71.234.51/verify?token=%s' % token
        send_mail_from = 'support@cilliai.com'
        recipients = [user.email]
        send_mail(subject, message, send_mail_from, recipients)
        response = send_otp(validated_data['phone_no'])
        if "success" not in response:
            return __badrequest__("Error while generating OTP")
        return user

    class Meta:
        unique_together = ('email',)
        model = User
        fields = (
            'id', 'password', 'email', 'username', 'phone_no'
        )
        extra_kwargs = {'password': {'write_only': True}}


class UpdateUserSerializer(serializers.ModelSerializer):
    def update(self, instance, validated_data):
        instance.email_verified = validated_data.get('email_verified', instance.email_verified)
        instance.phone_verified = validated_data.get('phone_verified', instance.phone_verified)
        instance.name = validated_data.get('name', instance.name)
        instance.email = validated_data.get('email', instance.email)
        instance.phone_no = validated_data.get('phone_no', instance.phone_no)
        instance.company_name = validated_data.get('company_name', instance.company_name)
        instance.address = validated_data.get('address', instance.address)
        instance.country = validated_data.get('country', instance.country)
        instance.pincode = validated_data.get('pincode', instance.pincode)
        instance.pan_number = validated_data.get('pan_number', instance.pan_number)
        instance.gst_number = validated_data.get('gst_number', instance.gst_number)
        instance.is_advertisor = validated_data.get('is_advertisor', instance.is_advertisor)
        instance.is_signage_owner = validated_data.get('is_signage_owner', instance.is_signage_owner)
        instance.from_time = validated_data.get('from_time', instance.from_time)
        instance.to_time = validated_data.get('to_time', instance.to_time)
        instance.category = validated_data.get('category', instance.category)
        instance.profile_picture = validated_data.get('profile_picture', instance.profile_picture)
        instance.reset_token = validated_data.get('reset_token', instance.reset_token)
        instance.save()
        return instance

    class Meta:
        model = User
        fields = (
            'id', 'name', 'email_verified', 'phone_verified', 'email', 'phone_no', 'auth_token',
            'company_name', 'address', 'country', 'pincode', 'pan_number', 'gst_number',
            'is_advertisor', 'is_signage_owner', 'from_time', 'to_time', 'category', 'profile_picture',
            'reset_token'
        )
        read_only_fields = ('auth_token',)


class UserSerializer(serializers.ModelSerializer):
    profile_picture = FileSerializer()

    class Meta:
        unique_together = ('email',)
        model = User
        fields = (
            'id', 'password', 'email', 'name', 'auth_token', 'email_verified', 'phone_verified',
            'phone_no', 'company_name', 'address', 'country', 'pincode', 'pan_number', 'gst_number',
            'is_advertisor', 'is_signage_owner', 'from_time', 'to_time', 'category', 'profile_picture',
            'reset_token'
        )
        read_only_fields = ('auth_token',)

这是有趣的部分。当我在指向UserViewSet的路由上发出PUT请求时,在get_serializer_class方法中返回了UpdateUserSerializer,但碰巧是未调用UpdateUserSerializer类中的update方法。

这是我得到的答复:

  

{“电子邮件”:[“此字段为必填。”],“ phone_no”:[“此字段为必填。”]}

1 个答案:

答案 0 :(得分:0)

这是API的验证错误。默认情况下,每个模型字段的空白将为false。我可以看到在您的用户模型中,电子邮件 phone_no 字段的空白未设置为True。因此,这里发生的是,当您发送不带电子邮件和phone_no的请求时,将收到此类验证错误。一种快速的解决方案是在用户模型的电子邮件 phone_no 字段中都添加 blank = True

更改您的用户模型中的以下代码并进行迁移。

email = models.EmailField('Email  address', unique=True, blank=True)
phone_no = models.CharField('Phone Number', max_length=255, unique=True, blank=True)

在用户序列化器中添加此代码

email = serializers.EmailField(required=False)
phone_no = serializers.CharField(required=False)

这是Django文档空白字段的链接。 https://docs.djangoproject.com/en/2.2/ref/models/fields/#blank