代码之家  ›  专栏  ›  技术社区  ›  Sreekanth Reddy Balne

如何在ModelSerializer的create方法中实现update_或_create

  •  0
  • Sreekanth Reddy Balne  · 技术社区  · 6 年前

    代码:

    class OTP(AppModel):
        phone_regex = RegexValidator(regex=r'^[6789]\d{9}$', message="phone no. is invalid.")
        phone_number = models.CharField(validators=[phone_regex], max_length=10, unique=True)
        code = models.CharField(max_length=255)
    
        def __str__(self):
            return str(self.phone_number) + ": "+str(self.code)
    
    class OTPSerializer(serializers.ModelSerializer):
        code = serializers.CharField(max_length=None, required=False)
        class Meta:
            model = OTP
            fields = ('id', 'code', 'phone_number')
            read_only_fields=('id', 'code')
    
        @transaction.atomic
        def create(self, validated_data):
            phone_number = validated_data.pop("phone_number")
            otp, created = OTP.objects.update_or_create(
                phone_number=phone_number, defaults={"code": generate_otp()})
            return otp
    

    我正试着去做 update_or_create 里面 create 方法 django-rest-framework ModelSerializer

    但是,这个领域 phone_number 模型内部 OTP 必须是 unique . 因此 unique=True .

    我能发布一个 电话号码 然后创建对象。但是,张贴同样的 电话号码 再次抛出错误 otp with this phone number already exists ,而不是更新它,如果它已经存在,因为我已经重写了 创造 方法。请帮助!

    1 回复  |  直到 6 年前
        1
  •  0
  •   pomo_mondreganto    6 年前

    你可以 phone_number 不需要,然后手动进行检查。你得到了错误,因为drf验证了 电话号码 在你之前。因此,基本上,解决方案可以是以下(仅限于serialiser代码):

    class OTPSerializer(serializers.ModelSerializer):
        code = serializers.CharField(max_length=None, required=False)
        class Meta:
            model = OTP
            fields = ('id', 'code', 'phone_number')
            read_only_fields=('id', 'code')
            extra_kwargs = {'phone_number': {'required': False}}
    
        @transaction.atomic
        def create(self, validated_data):
            phone_number = validated_data.pop("phone_number")
            otp, created = OTP.objects.update_or_create(
            phone_number=phone_number, defaults={"code": generate_otp()})
            return otp