I want to implement update_or_create when deserializing object. I found @K-Moe answer in this question: Django Rest Framework POST Update if existing or create
I tried this solution but I got the ValidationError saying that my object already exists:
[{'variant_id': [ErrorDetail(string='sku with this variant id already exists.', code='unique')]}, {'variant_id': [ErrorDetail(string='sku with this variant id already exists.', code='unique')]}]
Did I miss something?
My model
class Sku(models.Model):
variant_id = models.CharField(primary_key=True, max_length=10, validators=[MinLengthValidator(10)])
name = models.CharField(max_length=255)
shop = models.ForeignKey(Shop, related_name='sku', on_delete=models.CASCADE)
barcode = models.CharField(max_length=60, null=True, blank=True)
price = models.FloatField(null=True, blank=True)
def __str__(self):
return self.name
class Meta:
constraints = [
models.UniqueConstraint(fields=['variant_id', 'shop'], name='unique_shop_sku')
]
@classmethod
def update_or_create(cls, variant_id, shop_id, **kwargs):
with transaction.atomic():
return cls.objects.update_or_create(variant_id=variant_id, shop_id=shop_id, defaults=kwargs)
My serializers:
class SkuSerializer(serializers.ModelSerializer):
shop_id = serializers.CharField(source='shop')
class Meta:
model = Sku
fields = ['name', 'shop_id', 'product_id', 'variant_id', 'barcode', 'price']
def create(self, validated_data):
sku = Sku.update_or_create(
variant_id=validated_data.pop('variant_id'),
shop_id=validated_data.pop('shop'),
**validated_data
)
return sku