Как реализовать update_or_create внутри метода создания ModelSerializer - PullRequest
0 голосов
/ 12 января 2019

код:

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.

Мне удалось опубликовать phone_number и создать объект. Но повторная публикация того же phone_number выдает ошибку otp with this phone number already exists вместо ее обновления, если она уже существует, поскольку я переопределил метод create. Пожалуйста, помогите!

1 Ответ

0 голосов
/ 12 января 2019

Вы можете сделать phone_number НЕ обязательным, а затем выполнить проверку вручную. Вы получаете ошибку, потому что DRF проверял phone_number перед вами. Таким образом, в основном решение может быть следующим (только код сериализатора):

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...