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 = None class 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 = VendorContacts fields = ( ... 'email',) class VendorsSerializer(serializers.ModelSerializer): contacts = VendorContactSerializer(many=True) class Meta: model = Vendors fields = (... '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 = VendorsSerializer def 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 when validating 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 = Vendors fields = (... '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 def 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 = Vendors fields = (... '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.