If I need to change some field values before saving to the database as I think models method clear()
is suitable. But I can't call him despite all my efforts.
For example fields email I need set to lowercase and fields nda I need set as null
models.py
class Vendors(models.Model):nda = models.DateField(blank=True, null=True)parent = models.OneToOneField('Vendors', models.DO_NOTHING, blank=True, null=True)def clean(self):if self.nda == "":self.nda = Noneclass VendorContacts(models.Model):....vendor = models.ForeignKey('Vendors', related_name='contacts', on_delete=models.CASCADE)email = models.CharField(max_length=80, blank=True, null=True, unique=True)def clean(self):if self.email:self.email = self.email.lower()
serializer.py
class VendorContactSerializer(serializers.ModelSerializer):class Meta:model = VendorContactsfields = (...'email',)class VendorsSerializer(serializers.ModelSerializer):contacts = VendorContactSerializer(many=True)class Meta:model = Vendorsfields = (...'nda','contacts',)def create(self, validated_data):contact_data = validated_data.pop('contacts')vendor = Vendors.objects.create(**validated_data)for data in contact_data:VendorContacts.objects.create(vendor=vendor, **data)return vendor
views.py
class VendorsCreateView(APIView):"""Create new vendor instances from form"""permission_classes = (permissions.AllowAny,)serializer_class = VendorsSerializerdef post(self, request, *args, **kwargs):serializer = VendorsSerializer(data=request.data)try:serializer.is_valid(raise_exception=True)serializer.save()except ValidationError:return Response({"errors": (serializer.errors,)},status=status.HTTP_400_BAD_REQUEST)else:return Response(request.data, status=status.HTTP_200_OK)
As I learned from the documentation
Django Rest Framework serializers do not call the Model.clean whenvalidating model serializers
In dealing with this problem, I found two ways to solve it. 1. using the custom method at serializer. For my case, it looks like
class VendorsSerializer(serializers.ModelSerializer):contacts = VendorContactSerializer(many=True)
class Meta:model = Vendorsfields = (...'nda','contacts',)def create(self, validated_data):contact_data = validated_data.pop('contacts')vendor = Vendors.objects.create(**validated_data)for data in contact_data:VendorContacts.objects.create(vendor=vendor, **data)return vendordef validate(self, attrs):instance = Vendors(**attrs)instance.clean()return attrs
- Using
full_clean()
method. For me, it looks like
class VendorsSerializer(serializers.ModelSerializer):contacts = VendorContactSerializer(many=True)
class Meta:model = Vendorsfields = (...'nda','contacts',)def create(self, validated_data):contact_data = validated_data.pop('contacts')vendor = Vendors(**validated_data)vendor.full_clean()vendor.save()for data in contact_data:VendorContacts.objects.create(vendor=vendor, **data)return vendor
But in both cases, the clean() method is not called. I really don't understand what I'm doing wrong.