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