DRF: how to change the value of the model fields before saving to the database

2024/10/11 8:25:49

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
  1. 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.

Answer

For DRF you can change your serializer before save as below...

First of all, you should check that serializer is valid or not, and if it is valid then change the required object of the serializer and then save that serializer.

if serializer.is_valid():serializer.object.user_id = 15  # For example serializer.save() 

UPD! views.py

class VendorsCreateView(APIView):"""Create new vendor instances from form"""permission_classes = (permissions.AllowAny,)serializer_class = VendorsSerializerdef post(self, request, *args, **kwargs):data = request.dataif data['nda'] == '':data['nda'] = Nonefor contact in data['contacts']:if contact['email']:print(contact['email'])contact['email'] = contact['email'].lower()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)
https://en.xdnf.cn/q/69793.html

Related Q&A

keep matplotlib / pyplot windows open after code termination

Id like python to make a plot, display it without blocking the control flow, and leave the plot open after the code exits. Is this possible?This, and related subjects exist (see below) in numerous ot…

socket python : recvfrom

I would like to know if socket.recvfrom in python is a blocking function ? I couldnt find my answer in the documentation If it isnt, what will be return if nothing is receive ? An empty string ? In…

pandas read_excel(sheet name = None) returns a dictionary of strings, not dataframes?

The pandas read_excel documentation says that specifying sheet_name = None should return "All sheets as a dictionary of DataFrames". However when I try to use it like so I get a dictionary of…

Plotly: How to assign specific colors for categories? [duplicate]

This question already has an answer here:How to define colors in a figure using Plotly Graph Objects and Plotly Express(1 answer)Closed 2 years ago.I have a pandas dataframe of electricity generation m…

Using nested asyncio.gather() inside another asyncio.gather()

I have a class with various methods. I have a method in that class something like :class MyClass:async def master_method(self):tasks = [self.sub_method() for _ in range(10)]results = await asyncio.gath…

AttributeError: type object Word2Vec has no attribute load_word2vec_format

I am trying to implement word2vec model and getting Attribute error AttributeError: type object Word2Vec has no attribute load_word2vec_formatBelow is the code :wv = Word2Vec.load_word2vec_format("…

Python - Core Speed [duplicate]

This question already has answers here:Getting processor information in Python(12 answers)Closed 8 years ago.Im trying to find out where this value is stored in both windows and osx, in order to do som…

App Engine, transactions, and idempotency

Please help me find my misunderstanding.I am writing an RPG on App Engine. Certain actions the player takes consume a certain stat. If the stat reaches zero the player can take no more actions. I start…

Speed differences between intersection() and object for object in set if object in other_set

Which one of these is faster? Is one "better"? Basically Ill have two sets and I want to eventually get one match from between the two lists. So really I suppose the for loop is more like:f…

Pandas.read_csv reads all of the file into one column

I have a csv file in the form "...","...","..."... with over 40 columns. When I used this simple code, it only gives me one massive key. Ive been messing with it for over …