Le code:
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
J'essaye de faire update_or_create
dans la méthode create
du django-rest-
.ModelSerializer
du framework
Mais, le champ phone_number
à l'intérieur du modèle OTP
doit être unique
. D'où le unique=True
.
J'ai pu poster un phone_number
et créer l'objet. Mais, publier le même phone_number
renvoie à nouveau l'erreur otp avec ce numéro de téléphone existe déjà
, au lieu de le mettre à jour s'il existe déjà car j'ai remplacé le create code> méthode. Veuillez aider!
3 Réponses :
Vous pouvez rendre phone_number
NON obligatoire, puis effectuer manuellement la vérification. Vous obtenez l'erreur, car DRF a validé phone_number
avant vous. Donc, en gros, la solution pourrait être la suivante (code du sérialiseur uniquement):
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
Non, le phone_number
est obligatoire. Et le problème est: UniqueValidator
valide avant d'atteindre la méthode create
.
Essayez de définir le validateur dans votre classe de sérialiseur plutôt que dans la classe de modèle. Alors, faites ressembler votre classe de sérialiseur à quelque chose comme ceci:
class OTPSerializer(serializers.ModelSerializer): code = serializers.CharField(max_length=None, required=False) phone_regex = RegexValidator(regex=r'^[6789]\d{9}$', message="phone no. is invalid.") # add this line phone_number = serializers.CharField(validators=[phone_regex]) # and this line 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
Vous pouvez utiliser Signals pour le faire de manière propre. Simplement, vous pouvez envoyer une variable créée
à un récepteur
que vous définissez, et la traiter en fonction de la création ou non de votre objet. dans le cas de la réponse REST, remplacez simplement la méthode create
dans le sérialiseur pour renvoyer des données en fonction de l'état dans lequel vous vous trouvez, ou la méthode get / post / patch
vous utilisez dans l'APIView pour ne pas renvoyer serializer.data
, mais renvoyer à la place ce que vous voulez.
Voici un exemple de récepteur de signal:
@receiver(post_save, sender=settings.OTP_MODEL) def update(sender, instance=None, created=False, **kwargs): if created: # Do Something else: # Do Some Other thing